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;
}
posted @ 2024-05-11 17:05  xx019  阅读(3)  评论(0)    收藏  举报