1. 程式人生 > 實用技巧 >Yoi #435. 團不過

Yoi #435. 團不過

題面


分析

顯然容斥,用全部方案數-先手必敗(異或和為0)

設總方案為\(g_{i}=(2^{n}-1)^{\underline{i}}\)

考慮異或和為0的方案數\(f_{n}\)

列舉最後一堆石子,前n-1堆石子隨便取,總共\(g_{n-1}\)

但前n-1堆石子可能是0,要減去\(f_{n-1}\)

而第n堆石子還有可能與前面相同,要減去\((n-1)f_{n-2}(2^n-i+1)\)

時間複雜度\(O(n)\)

#include<bits/stdc++.h>
#define ll long long
const int p=1e9+7;
using namespace std;

inline int ksm(ll a,int b) {
	ll ret=1;
	while(b) {
		if(b&1) ret=ret*a%p;
		a=a*a%p,b>>=1;
	}
	return ret;
}
inline int mo(int x) {
	return x>=p?x-p:x;
}

const int N=1e7+5;
int n,f[N],g[N];

int main() {
	freopen("yui.in","r",stdin);
	freopen("yui.out","w",stdout);
	scanf("%d",&n);
	int t=mo(ksm(2,n)-1+p); g[1]=t;
	for(int i=2;i<=n;i++) {
		g[i]=(ll)g[i-1]*(t-i+1)%p;
	}
	f[1]=f[2]=0;
	for(int i=3;i<=n;i++) {
		f[i]=(((ll)g[i-1]-f[i-1]-(ll)(i-1)*f[i-2]%p*(t+2-i)%p)%p+p)%p;
	}
	printf("%d\n",mo(g[n]-f[n]+p));
	return 0;
}