@bzoj - 4589@ Hard Nim

Posted tiw-air-oao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了@bzoj - 4589@ Hard Nim相关的知识,希望对你有一定的参考价值。

目录


@[email protected]

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

@[email protected]

根据常识,异或起来等于 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 [email protected]

#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]);
    }
}

@[email protected]

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
















以上是关于@bzoj - 4589@ Hard Nim的主要内容,如果未能解决你的问题,请参考以下文章

@bzoj - 4589@ Hard Nim

bzoj4589: Hard Nim fwt

bzoj 4589: Hard Nim

bzoj 4589 Hard Nim——FWT

BZOJ4589. Hard Nim

BZOJ4589. Hard Nim