bzoj4589 Hard Nim(fwt_xor+快速幂,fwt入门题)
Posted live4m
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj4589 Hard Nim(fwt_xor+快速幂,fwt入门题)相关的知识,希望对你有一定的参考价值。
题意:
解法:
nim必胜的条件为石子数量异或和为0.
那么题意可以转化为:
从<=m的质数中,可重复的选出n个数,最后异或和为0的方案数.
n<=1e9,m<=5e4
令f[i][j]为选i个数,异或和为i的方案数
f[i][j]+=f[i-1][x]*f[1][y],其中x^y=j.
其实就是f[1][]异或卷积n次,
用fwt优化异或卷积的速度,用快速幂优化异或卷积的次数即可.
code:
#include<bits/stdc++.h>
#define int long long
#define PI pair<int,int>
using namespace std;
int ppow(int a,int b,int mod){
int ans=1%mod;a%=mod;
while(b){if(b&1)ans=1ll*ans*a%mod;a=1ll*a*a%mod;b>>=1;}
return ans;
}
const int mod=1e9+7;
const int maxm=2e5+5;
const int inv2=ppow(2,mod-2,mod);
int p[maxm],c;
int np[maxm];
int a[maxm];
int ans[maxm];
int n,m;
int len;
void init(){
for(int i=2;i<maxm;i++){
if(!np[i]){
p[c++]=i;
for(int j=i+i;j<maxm;j+=i){
np[j]=1;
}
}
}
}
void fwt_xor(int *a, int op){
for(int i=1;i<len;i<<=1){
for(int j=0,p=i<<1;j<len;j+=p){
for(int k=0;k<i;k++){
int x=a[j+k],y=a[i+j+k];
a[j+k]=(x+y)%mod;
a[i+j+k]=(x-y+mod)%mod;
if(op==-1){
a[j+k]=1ll*a[j+k]*inv2%mod;
a[i+j+k]=1ll*a[i+j+k]*inv2%mod;
}
}
}
}
}
void f_pow(int *a,int n){
for(int i=0;i<len;i++)ans[i]=0;
ans[0]=1;
fwt_xor(a,1);
fwt_xor(ans,1);
while(n){
if(n&1){
for(int i=0;i<len;i++){
ans[i]=1ll*ans[i]*a[i]%mod;
}
}
for(int i=0;i<len;i++){
a[i]=1ll*a[i]*a[i]%mod;
}
n>>=1;
}
fwt_xor(ans,-1);
}
void solve(){
len=1;
while(len<m*2)len<<=1;//因为异或会使得值域翻倍,所以这里取上限为m*2
for(int i=0;i<len;i++)a[i]=0;
for(int i=0;i<c;i++){
if(p[i]>m)break;
a[p[i]]=1;
}
f_pow(a,n);
int res=ans[0];
cout<<res<<endl;
}
signed main(){
#ifndef ONLINE_JUDGE
freopen("../in.txt","r",stdin);
freopen("../out.txt","w",stdout);
#endif
ios::sync_with_stdio(0);cin.tie(0);
init();
while(cin>>n>>m){
solve();
}
return 0;
}
以上是关于bzoj4589 Hard Nim(fwt_xor+快速幂,fwt入门题)的主要内容,如果未能解决你的问题,请参考以下文章