2024杭电多校1

1008.位运算

题意:
[0,2m)[0,2^m)[0,2m)中选四个数满足a⊗b⊕c⊖d=na⊗b⊕c⊖d=nabcd=n,问有多少种可能性

题解:
我们关注数的二进制的每一位,12的方案数为 4, 1的方案数为 4,把每一位的方案数乘一下就可以了

代码:

#include <bits/stdc++.h>
#define int long long
using ll = long long;
using PII = std::array<int, 2>;
using namespace std;
const ll INF = 2E18 + 10;
#ifdef __clang__
template <typename T>
inline int my_lg(T n) {
    return (n > 0) ? static_cast<int>(log2(n)) : -1;
}
#define __lg my_lg
#define __gcd gcd
#endif
#ifndef ONLINE_JUDGE
#include "_debug.h"
#define EL std::cout << "\n";
#define COUT(ITEM) std::cout << #ITEM << "=" << ITEM << '\n';
#define CERR(ITEM) std::cerr << #ITEM << "=" << ITEM << '\n';
#endif
// struct cmp{bool operator()(const int & x, const int &y) const{ return x<y;
// }};
const int N = 2E6 + 10;

void SINGLE_TEST() {
    int n, k;
    cin >> n >> k;
    ll anss = 1;
    for (int b = k; b >= 0; b--) {
        int t = (n >> b & 1);
        ll ans = 0;
        if (t == 1) {
            ans += 8 + 4;
        } else {
            ans += 4;
        }
        anss *= ans;
    }
    cout << anss / 4 << "\n";
}

signed main() {
    cin.tie(nullptr)->sync_with_stdio(false);

    int SAMPLES = 1;
    cin >> SAMPLES;
    while (SAMPLES--) SINGLE_TEST();
}

1002.星星

题意:
nnn次机会,第iii次机会,aia_iai的代价获得1颗星星,bib_ibi的代价获得2颗星星,aia_iai的代价获得3颗星星,did_idi的代价获得4颗星星。也可以跳过这一次机会
问获得kkk颗星星的最小代价是多少。

题解:
nnn的范围不大,就是背包dp就可以了。

#include <bits/stdc++.h>
#define int long long
using ll = long long;
using PII = std::array<int, 2>;
using namespace std;
const ll INF = 2E18 + 10;
#ifdef __clang__
template <typename T>
inline int my_lg(T n) {
    return (n > 0) ? static_cast<int>(log2(n)) : -1;
}
#define __lg my_lg
#define __gcd gcd
#endif
#ifndef ONLINE_JUDGE
#include "_debug.h"
#define EL std::cout << "\n";
#define COUT(ITEM) std::cout << #ITEM << "=" << ITEM << '\n';
#define CERR(ITEM) std::cerr << #ITEM << "=" << ITEM << '\n';
#endif
// struct cmp{bool operator()(const int & x, const int &y) const{ return x<y;
// }};
const int N = 2E6 + 10;

void SINGLE_TEST() {
    int n, k;
    cin >> n >> k;
    vector<int> a(n + 1), b(n + 1), c(n + 1), d(n + 1);
    for (int i = 1; i <= n; i++) {
        cin >> a[i] >> b[i] >> c[i] >> d[i];
    }
    vector<int> dp(k + 1, INF);
    dp[0] = 0;
    for (int id = 1; id <= n; id++) {
        for (int i = k; i >= 0; i--) {
            if (i - 1 >= 0) {
                dp[i] = min(dp[i], dp[i - 1] + a[id]);
            }
            if (i - 2 >= 0) {
                dp[i] = min(dp[i], dp[i - 2] + b[id]);
            }
            if (i - 3 >= 0) {
                dp[i] = min(dp[i], dp[i - 3] + c[id]);
            }
            if (i - 4 >= 0) {
                dp[i] = min(dp[i], dp[i - 4] + d[id]);
            }
        }
        // CERR(i)
    }
    cout << dp[k] << "\n";
}

signed main() {
    cin.tie(nullptr)->sync_with_stdio(false);

    int SAMPLES = 1;
    cin >> SAMPLES;
    while (SAMPLES--) SINGLE_TEST();
}

1001.循环位移

题意:
字符串aaa,可以左移循环变为不同的字符串。把这些字串设为集合[a]。
问字符串bbb的连续字串有多少字串是在[a]中。

题解:
字符串hash,把集合[a],的所有字符串存储起来,再遍历字符串b的字串,假如出现在[a]中就答案+1

代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
 
typedef unsigned long long ULL;
const int N = 2e6+10,P = 131;
ULL h[N],p[N];
ULL h2[N],p2[N];
int n,m;
string s,t;
//计算1~i的哈希值
ULL get(int l,int r)
{
    return h[r] - h[l-1] * p[r-l+1];    
}
ULL get2(int l,int r)
{
    return h2[r] - h2[l-1] * p2[r-l+1];    
}
map<ULL,int>mp;
void solve()
{
    
    cin>>s>>t;
    n=s.size(),m=t.size();
    s=s+s;
    s=' '+s;
    t=' '+t;
    h[0] = 0,p[0] = 1;
    //预处理哈希值的前缀和
    n*=2;
    int x=n/2;

    h[0] = 0,p[0] = 1;
    h2[0] = 0,p2[0] = 1;
    for(int i=1;i<=n;i++)
    {
        p[i] = p[i-1] * P;
        h[i] = h[i-1] * P + s[i];
    }
    
    for(int i=x;i<n;i++){
        mp[get(i-x+1,i)]=1;
        
    }
    for(int i=1;i<=m;i++){
        p2[i] = p2[i-1] * P;
        h2[i] = h2[i-1] * P + t[i];
    }
    
    int ans=0;
    for(int i=x;i<=m;i++){
        if(mp[get2(i-x+1,i)])ans++;
    }
    cout<<ans<<'\n';
    mp.clear();
}
signed main()
{
    int T=1;
    cin>>T;
    while(T--){
        solve();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值