1008.位运算
题意:
在[0,2m)[0,2^m)[0,2m)中选四个数满足a⊗b⊕c⊖d=na⊗b⊕c⊖d=na⊗b⊕c⊖d=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();
}
}