kmjp's blog

競技プログラミング参加記です

AtCoder ARC #146 : C - Even XOR

出来の悪かった回。
https://atcoder.jp/contests/arc146/tasks/arc146_c

問題

整数Nが与えられる。
0以上2^N未満の整数の集合Sのうち、以下を満たすのは何通りか。

  • Sの空でない部分集合Tは、要素数が奇数がXORを取ると非0かのいずれかを満たす。

解法

dp(k) := 条件を満たすk要素のS
とする。dp(0)=1、dp(1)=2^Nである。
以後、dp(k)からdp(k+1)を求めて行く。

k要素のSに新たな要素を加えることを考える。
Sの部分集合のうち奇数要素のxorとなるものは足せない。逆にそうでないものは足せるので、dp(k+1)=dp(k)*(2^N-2^(k-1))となる。

int N;
const ll mo=998244353;

ll dp[202020];
ll modpow(ll a, ll n = mo-2) {
	ll r=1;a%=mo;
	while(n) r=r*((n%2)?a:1)%mo,a=a*a%mo,n>>=1;
	return r;
}

void solve() {
	int i,j,k,l,r,x,y; string s;
	
	cin>>N;
	
	dp[0]=1;
	dp[1]=modpow(2,N);
	ll ret=dp[0]+dp[1];
	for(i=2;i<=N+1;i++) {
		dp[i]=dp[i-1]*(mo+modpow(2,N)-modpow(2,i-2))%mo*modpow(i)%mo;
		ret+=dp[i];
	}
	
	cout<<ret%mo<<endl;
}

まとめ

これはすんなり解いておきたかったな…。