CF1815D. XOR Counting
看了题解之后有点震惊,果然我没有足够的注意力。
注意到,当 \(m=1\) 时,答案就是 \(n\);当 \(m\ge 3\) 时,显然所有与 \(n\) 同奇偶的都能凑出来,且 \(a_1\oplus a_2\oplus\ldots a_m\) 的奇偶性与 \(a_1+a_2+\ldots a_m=n\) 的奇偶性相同,所以能凑出的就是这些数。于是我们只需要考虑 \(m=2\) 的情况。
记 \(f_n\) 表示 \(n\) 的答案,\(g_n\) 表示 \(a_1\oplus a_2\) 的方案数。当 \(n\) 为奇数时,不妨令 \(a_1\) 为奇数,\(a_2\) 为偶数,那么令 \(b_1=\dfrac{a_1-1}{2},b_2=\dfrac{a_2}{2}\),则 \(b_1+b_2=\dfrac{n-1}{2}\),\(f(n)=2f(\dfrac{n-1}{2})+g(\dfrac{n-1}{2})\),\(g(n)=g(\dfrac{n-1}{2})\);当 \(n\) 为偶数时,同理有 \(f(n)=2f(\dfrac{n}{2})+2f(\dfrac{n}{2}-1)\),\(g(n)=g(\dfrac{n}{2})+g(\dfrac{n}{2}-1)\)。递推即可。
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=998244353;
inline int read(){
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
map<int,int>f,g;
int G(int n){
if(n<0)return 0;
if(n==0)return 1;
if(g.count(n))return g[n];
if(n%2==1)return g[n]=G((n-1)/2);
else return g[n]=(G(n/2)+G(n/2-1))%mod;
}
int F(int n){
if(n<0)return 0;
if(n==0)return 0;
if(f.count(n))return f[n];
if(n%2==1)return f[n]=(2*F((n-1)/2)+G((n-1)/2))%mod;
else return f[n]=(2*F(n/2)+2*F(n/2-1))%mod;
}
void solve(){
int n=read(),m=read();
if(m==1)return printf("%lld\n",n%mod),void();
if(m>=3){
if(n%2==0)return printf("%lld\n",((n/2)%mod)*(((n+2)/2)%mod)%mod),void();
else return printf("%lld\n",(((n+1)/2)%mod)*(((n+1)/2)%mod)%mod),void();
}
printf("%lld\n",F(n));
}
signed main(){
int T=read();
while(T--){
solve();
}
return 0;
}

浙公网安备 33010602011771号