Luogu P5363は[SDOI2019】硬貨を移動させます

質問が言うのに長い時間のためにプッシュするに知恵を置くことを言って、申し訳ありませんが233を自分でオフに書きません

まず、あなたが知っている必要がありますと呼ばれるラダーニムのあなたが見ることができる何かの特定このブログを

この質問して、我々はニムの梯子の数あたりの石の2つの金貨の山の間の距離として見てきました、この関係は非常に明確で見つかりました

ラダーニムの結論を考えてみましょう:石の奇数XORヒープとし\(0 \)と我々はDPアウト非常に暴力的に従事できることを見出しました

\(F_ {I、J、 Kは} \) の前に放電電流を表す\(Iは\)石の総数であるとスタック石、(J \)を\、前記石の奇数スタックと、排他的OR \(K \)プログラムの数は、現在のスタックを列挙する転送時間は、複雑に直接いくつかのかかった\(O(N ^ 3 \倍メートル)\)この問題を渡すことはできません明らかに、

さんは落ち着いてみようとすることを条件見つかっXORは、その後、決定的バイナリの視点から考えると

撥外観を導入するので、\(F_ {I、J} \) の前に行わ表し\(Iは\)ビット、奇数スタックとする(Jを\)\と排他的論理和とする(0 \)\スキーム番号最後に、とパーティションの法律、その後の状況でも、統合スタック\(^ C_Nメートルの\)マイナス缶

その後、我々は、低ビットに高列挙、DPは非常に良いです移し、その後、奇数ヒープを列挙し、残りはこの1つがされて列挙する\(1 \)はスタックの奇数である(明らかさえなければなりません)、次いで、組み合わせの数は、転送に時間がかかります

複雑\(O(NM \タイムズ\ N-ログ)\)この質問によって、十分なデータ範囲。もちろん、この問題は、次にキャリー視点の使用を含む方法を用いてMTT最適化\(O(M \ログMの \ログn)を\) 優良事例のだから、233の拡張版であります

#include<cstdio>
#define RI register int
#define CI const int&
using namespace std;
const int N=200005,R=20,mod=1e9+9;
int n,m,f[R][N],odd,even,num,ret,fact[N],inv[N];
inline void inc(int& x,CI y)
{
    if ((x+=y)>=mod) x-=mod;
}
inline int sub(CI x,CI y)
{
    int t=x-y; return t<0?t+mod:t;
}
inline int quick_pow(int x,int p=mod-2,int mul=1)
{
    for (;p;p>>=1,x=1LL*x*x%mod) if (p&1) mul=1LL*mul*x%mod; return mul;
}
inline void init(CI n)
{
    RI i; for (fact[0]=i=1;i<=n;++i) fact[i]=1LL*fact[i-1]*i%mod;
    for (inv[n]=quick_pow(fact[n]),i=n-1;~i;--i) inv[i]=1LL*inv[i+1]*(i+1)%mod;
}
inline int C(CI n,CI m)
{
    return 1LL*fact[n]*inv[m]%mod*inv[n-m]%mod;
}
int main()
{
    RI i,j,k; scanf("%d%d",&n,&m); init(n+m);
    for (odd=m+1>>1,even=m+1-odd,num=n-m,f[R-1][num]=1,i=R-2;~i;--i)
    for (j=0;j<=num;++j) for (k=0;j+(1<<i)*k<=num&&k<=odd;k+=2)
    inc(f[i][j],1LL*f[i+1][j+(1<<i)*k]*C(odd,k)%mod);
    for (i=0;i<=num;++i) inc(ret,1LL*f[0][i]*C(i+even-1,even-1)%mod);
    return printf("%d",sub(C(n,m),ret)),0;
}

おすすめ

転載: www.cnblogs.com/cjjsb/p/11619663.html