【SRM】518 Nim

题意

\(K(1 \le K \le 10^9)\)堆石子,每堆石子个数不超过\(L(2 \le 50000)\),问Nim游戏中先手必败局面的数量,答案对\(10^9+7\)取模。

分析

容易得到\(f(i, k) = \sum_{j=0}^{n-1} f(i-1, j) f(i-1, k^j), f(1, i(2 \le i \le L))=1\),其中\(n=min(2^i, 2^i > L)\)。发现其实这就是操作为\(xor\)的卷积。于是用鬼畜的fwt做就行了。

题解

然后fwt+快速幂即可。

// BEGIN CUT HERE

// END CUT HERE
#line 5 "Nim.cpp"
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
const int mo=1e9+7, N=100005, two=(1e9+8)/2;
void fwt(int *a, int l, int r, int f) {
	if(r-l==1) {
		return;
	}
	int mid=(l+r)>>1;
	if(!f) {
		fwt(a, l, mid, f);
		fwt(a, mid, r, f);
	}
	int g=f?two:1;
	for(int i=l, m=(r-l)>>1; i<mid; ++i) {
		int x=a[i], y=a[i+m];
		a[i]=(ll)(x+y)%mo*g%mo;
		a[i+m]=(ll)(x-y+mo)%mo*g%mo;
	}
	if(f) {
		fwt(a, l, mid, f);
		fwt(a, mid, r, f);
	}
}
int ipow(int a, int b) {
	int x=1;
	for(; b; b>>=1, a=(ll)a*a%mo) {
		if(b&1) {
			x=(ll)x*a%mo;
		}
	}
	return x;
}
int a[N];
class Nim {
public:
	int count(int K, int L) {
		int len=1;
		for(; len<=L; len<<=1);
		memset(a, 0, sizeof(int)*len);
		for(int i=2; i<=L; ++i) {
			a[i]=1;
		}
		for(int i=2; i<=L; ++i) {
			if(a[i]) {
				for(int j=i+i; j<=L; j+=i) {
					a[j]=0;
				}
			}
		}
		fwt(a, 0, len, 0);
		for(int i=0; i<len; ++i) {
			a[i]=ipow(a[i], K);
		}
		fwt(a, 0, len, 1);
		return a[0];
	}

// BEGIN CUT HERE
	public:
	void run_test(int Case) { if ((Case == -1) || (Case == 0)) test_case_0(); if ((Case == -1) || (Case == 1)) test_case_1(); if ((Case == -1) || (Case == 2)) test_case_2(); if ((Case == -1) || (Case == 3)) test_case_3(); }
	private:
	template <typename T> string print_array(const vector<T> &V) { ostringstream os; os << "{ "; for (typename vector<T>::const_iterator iter = V.begin(); iter != V.end(); ++iter) os << '\"' << *iter << "\","; os << " }"; return os.str(); }
	void verify_case(int Case, const int &Expected, const int &Received) { cerr << "Test Case #" << Case << "..."; if (Expected == Received) cerr << "PASSED" << endl; else { cerr << "FAILED" << endl; cerr << "\tExpected: \"" << Expected << '\"' << endl; cerr << "\tReceived: \"" << Received << '\"' << endl; } }
	void test_case_0() { int Arg0 = 3; int Arg1 = 7; int Arg2 = 6; verify_case(0, Arg2, count(Arg0, Arg1)); }
	void test_case_1() { int Arg0 = 4; int Arg1 = 13; int Arg2 = 120; verify_case(1, Arg2, count(Arg0, Arg1)); }
	void test_case_2() { int Arg0 = 10; int Arg1 = 100; int Arg2 = 294844622; verify_case(2, Arg2, count(Arg0, Arg1)); }
	void test_case_3() { int Arg0 = 123456789; int Arg1 = 12345; int Arg2 = 235511047; verify_case(3, Arg2, count(Arg0, Arg1)); }

// END CUT HERE

};

// BEGIN CUT HERE
int main() {
	Nim ___test;
	___test.run_test(-1);
	return 0;
}
// END CUT HERE
博客地址:www.cnblogs.com/iwtwiioi 本文为博主原创文章,未经博主允许不得转载。一经发现,必将追究法律责任。
posted @ 2015-11-22 18:52  iwtwiioi  阅读(1008)  评论(0编辑  收藏  举报