泉華子的OI足迹

Σ(っ°Д°;)っΣ(っ°Д°;)っΣ(っ°Д°;)っ

[BZOJ4589]-Hard Nim-FWT

说在前面

并没有什么想说的,但是要保持格式=w=


题目

BZOJ4589传送门

题面

Claris和NanoApe在玩石子游戏,他们有N堆石子,规则如下:
1. Claris和NanoApe两个人轮流拿石子,Claris先拿。
2. 每次只能从一堆中取若干个,可将一堆全取走,但不可不取,拿到最后1颗石子的人获胜。
Claris很好奇,如果这N堆石子满足每堆石子的初始数量是不超过M的质数,而且他们都会按照最优策略玩游戏,那么NanoApe能获胜的局面有多少种。
由于答案可能很大,你只需要给出答案对10^9+7取模的值。

输入输出格式

输入格式:
多组数据,EOF结束
每行两个整数N和M,含义如题

输出格式:
对于每组数据,输出答案


解法

emmmmm……
这道题还算比较简单吧,先写出dp式子:dp[i][j]表示,前i堆石子,异或和为j的方案数。
转移就是dp[i][j]=kp[r]=jdp[i1][k],其中p[r]是一个不大于M的质数,最后答案就是dp[N][0]

然后发现这就是一个异或卷积,于是构造数组b[],令b[i]=1 (i is prime),其余为0。对b[]求一个正变换,然后快速幂一下,再逆变换回去就好了


下面是自带大常数的代码

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;

const int P = 1e9 + 7 , inv2 = 500000004 ;
bool isnotp[50005] ;
int N , M , p[50005] , pcnt , a[100100] , tt ;

void preWork(){
    for( int i = 2 ; i <= 50000 ; i ++ ){
        if( !isnotp[i] ) p[++pcnt] = i ;
        for( int j = 1 ; j <= pcnt && i * p[j] <= 50000 ; j ++ ){
            isnotp[ i*p[j] ] = true ;
            if( i % p[j] == 0 ) break ;
        }
    } isnotp[1] = true ;
}

long long s_pow( long long x , int b ){
    long long rt = 1 ;
    while( b ){
        if( b&1 ) rt = rt * x %P ;
        x = x * x %P , b >>= 1 ;
    } return rt ;
}

void FWT( int *a , int lf , int rg , bool rev ){
    if( lf == rg ) return ;
    int siz = ( rg - lf + 1 ) >> 1 , t0 , t1 ;
    FWT( a , lf , lf + siz - 1 , rev ) ;
    FWT( a , rg - siz + 1 , rg , rev ) ;
    for( int i = lf + siz - 1 ; i >= lf ; i -- ){
        t0 = a[i] , t1 = a[i+siz] ;
        if( rev ){
            a[i] = 1LL * ( t0 + t1 ) * inv2 %P ;
            a[i+siz] = 1LL * ( t0 - t1 ) * inv2 %P ;
        } else a[i] = ( t0 + t1 )%P , a[i+siz] = ( t0 - t1 )%P ;
    }
}

void solve(){
    for( int i = 1 ; i <= M ; i ++ )
        if( !isnotp[i] ) a[i] = 1 ;
    for( tt = 1 ; tt <= M ; tt <<= 1 ) ;
    FWT( a , 0 , tt - 1 , 0 ) ;
    for( int i = 0 ; i < tt ; i ++ )
        a[i] = s_pow( a[i] , N ) ;
    FWT( a , 0 , tt - 1 , 1 ) ;
    printf( "%d\n" , ( a[0] + P )%P ) ;
}

int main(){
    preWork() ;
    while( scanf( "%d%d" , &N , &M ) != EOF ){
        memset( a , 0 , M << 3 ) ;
        solve() ;
    }
}
阅读更多
版权声明:转载嘛....也不是不可以(故作沉思),记得带上me的ID啊qwq https://blog.csdn.net/Izumi_Hanako/article/details/79960961
个人分类: FFT-NTT-FWT-FMT
相关热词: bzoj4589
上一篇[UOJ#310]-黎明前的巧克力-FWT的可加性
下一篇[HDU6057]-Kanade's convolution-FWT子集卷积
想对作者说点什么? 我来说一句

Learn More Python 3 the Hard Way epub

2017年10月06日 6.16MB 下载

learn c the hard way

2015年11月05日 1.67MB 下载

Learn Vimscript the Hard Way

2016年05月18日 12.73MB 下载

Learn Python 3 The Hard Way

2017年07月27日 2.83MB 下载

learn python 3 the Hard Way

2017年09月13日 5.32MB 下载

Learning hard C#学习笔记+源码.rar

2017年07月11日 69.85MB 下载

没有更多推荐了,返回首页

关闭
关闭