zoukankan      html  css  js  c++  java
  • @bzoj


    @description@

    n 堆石子,每堆石子的数量是不超过 m 的一个质数。
    两个人玩 nim 游戏,问使后手必胜的初始局面有多少种。
    模 10^9 + 7。

    input
    多组数据。数据组数 <= 80。
    每组数据一行两个正整数,n 和 m。1 <= n <= 10^9, 2 <= m <= 50000。
    output
    对于每组数据,输出一行答案。

    sample input
    3 7
    4 13
    sample output
    6
    120

    @solution@

    根据常识,异或起来等于 0,nim 游戏就一定后手必胜。

    定义 dp(i, j) 前 i 堆石子异或起来等于 j 的方案数,则有转移:

    [dp(i, j) = sum_{kin S}dp(i-1, joplus k) ]

    其中 S 是小于等于 m 的质数集合,初始情况 dp(0, 0) = 1。

    这感觉起来像是一个卷积,但是又有点不像我们平常所见的卷积。
    定义 (f(i) = [iin S]),则 (dp(i,j)=sum f(k)*dp(i-1, joplus k))
    好的它就是一个异或卷积。

    我们的 dp(n)其实就是 f^n。因此,我们只需要先对 f 进行 FWT 正变换,再对每一个数进行快速幂,最后再 FWT 逆变换回来,f(0) 就是我们的答案。

    @accepted code@

    #include<cstdio>
    const int MAXN = 100000;
    const int MOD = int(1E9) + 7;
    const int INV = (MOD + 1) >> 1;
    int pow_mod(int b, int p) {
    	int ret = 1;
    	while( p ) {
    		if( p & 1 ) ret = 1LL*ret*b%MOD;
    		b = 1LL*b*b%MOD;
    		p >>= 1;
    	}
    	return ret;
    }
    int f[MAXN + 5], prm[MAXN + 5], pcnt = 0;
    bool isprm[MAXN + 5];
    void init() {
    	for(int i=2;i<=MAXN;i++) {
    		if( !isprm[i] ) {
    			prm[++pcnt] = i;
    			f[i] = 1;
    		}
    		for(int j=1;1LL*i*prm[j]<=MAXN;j++) {
    			isprm[i*prm[j]] = true;
    			if( i % prm[j] == 0 )
    				break;
    		}
    	}
    }
    void fwt(int *a, int n, int type) {
    	for(int s=2;s<=n;s<<=1) {
    		for(int i=0,t=(s>>1);i<n;i+=s) {
    			for(int j=0;j<t;j++) {
    				int x = a[i+j], y = a[i+j+t];
    				a[i+j] = 1LL*(x + y)%MOD*(type == 1 ? 1 : INV)%MOD;
    				a[i+j+t] = 1LL*(x + MOD - y)%MOD*(type == 1 ? 1 : INV)%MOD;
    			}
    		}
    	}
    }
    int g[MAXN + 5];
    int main() {
    	init(); int n, m;
    	while( scanf("%d%d", &n, &m) == 2 ) {
    		int len = 1; while( len <= m ) len <<= 1;
    		for(int i=0;i<len;i++)
    			g[i] = 0;
    		for(int i=1;i<=m;i++)
    			g[i] = f[i];
    		fwt(g, len, 1);
    		for(int i=0;i<len;i++)
    			g[i] = pow_mod(g[i], n);
    		fwt(g, len, -1);
    		printf("%d
    ", g[0]);
    	}
    }
    

    @details@

    我才不会说我因为初始化只把m以内的数清零然后WA好几遍呢。

  • 相关阅读:
    苹果一体机发射Wi-Fi
    iphone 屏蔽系统自动更新,消除设置上的小红点
    data parameter is nil 异常处理
    copy与mutableCopy的区别总结
    java axis2 webservice
    mysql 远程 ip访问
    mysql 存储过程小问题
    mysql游标错误
    is not writable or has an invalid setter method错误的解决
    Struts2中关于"There is no Action mapped for namespace / and action name"的总结
  • 原文地址:https://www.cnblogs.com/Tiw-Air-OAO/p/10274039.html
Copyright © 2011-2022 走看看