LINK:除算と剰余
ゴーストの問題。しかし、良い書き込みに50分。時分割DPを考慮せずに、それは実際には、カウントを組み合わせたものです。
除算演算ダウン分割プレスで形状を必要な時間を考慮してください。
除算演算を押圧するように、除算演算は、X字状の大きさに影響されないからです。
直接圧縮はまた、複雑1E4に到達ワイズほとんど13 2 2 ^ 13でバイナリ状態の数です。
そこに数x 2 wはハッシュのような圧力のxがある番号2である我々は状態を持って考えてみましょう。
この理由は、むしろスプレッドアウトよりも、彼らに同じことのいくつかをマージすることです。それは直接2を記録することができますどのように多くのより多くのです。
あなたは、5つの状態のほとんど唯一の比較的少量で、この異なる除数を見つけることができます。
どのようにハッシュにそのような決定を探しているP-バンドを使用してハッシュの次のバージョンは非常に便利もあるかを検討。
i番目のバンド(現在の数+1)を法のために、我々は100未満などの状態量を必要としません:そのような。
欠点をリークしていない見つけることができます。このハッシュは、我々は国家の代表が、それは次のようになり状態を取り除くために何を意味するかの値が何であるかを知っておく必要があるということです。
Xはそう状態の多数の遷移状態+ X 状態 xの現在値。
xは2と半分に分割したとき、後者は非常に低いそうする前の最初のステップの複雑さを考慮しているのx背後の現在の値が5000になっ何を半分にカットされます列挙する必要はありません5000のDP状態。
2で割ったときに、第2の部分が行います列挙転送することはできません私達の状態の多くの無効な状態のため、無効な見つけることができます。
(1/16が一定であることを言うようにすることができ、問題の解決策にこの問題。
元のDP転送を比較すると、重複存在はどのような相対的な関係に対処する必要がありますがある場合は数または%は時間の数で割ったことは注目に値するです。
前者はHを乗じて[W] //モジュロ上に配置された後、残りの数として表示される何度wです。これらの数字の間に存在していない配置が持っていたためです。
この後者の選択でも、[W]がG [j]はこの種のものプログラムが乗算されることを見出しました。
ハッシュ状態がゼロの数に注意を払う必要があるときときの表現の特定の数。2サイクルの注意が列挙を逆にする必要があり、DP。
非常に優れたDPの話題。
const int MAXN=200010,maxn=10010;
int a[MAXN],b[MAXN],q[MAXN],c[MAXN],w[MAXN],p[MAXN],vis[MAXN];
ll fac[MAXN<<1],inv[MAXN],in[MAXN],f[maxn][110];
int g[MAXN][10],v[MAXN],h[MAXN];
int n,m,maxx,s,top,sum,tot;
inline ll ksm(ll b,int p)
{
ll cnt=1;
while(p)
{
if(p&1)cnt=cnt*b%mod;
b=b*b%mod;p=p>>1;
}
return cnt;
}
inline void prepare()
{
fac[0]=1;in[1]=1;
rep(1,maxx,i)
{
fac[i]=fac[i-1]*i%mod;
if(i!=1)in[i]=(mod-mod/i)*in[mod%i]%mod;
}
inv[maxx]=ksm(fac[maxx],mod-2);
fep(maxx-1,0,i)inv[i]=inv[i+1]*(i+1)%mod;
}
inline void get_state()
{
int ww=0;
rep(1,sum,i)ww=ww*(w[i]+1)+q[i];
tot=max(tot,ww);
rep(1,sum,i)g[ww][i]=q[i],v[ww]+=q[i];
}
inline void dfs(int x)
{
if(x==sum+1)
{
get_state();
return;
}
rep(0,w[x],i)
{
q[x]=i;
dfs(x+1);
}
}
int main()
{
freopen("1.in","r",stdin);
get(s);get(n);get(m);maxx=n+m;
prepare();
rep(1,n,i)
{
get(a[i]);
if(a[i]>s){putl(fac[n+m]);return 0;}
}
ll ww=1;
rep(1,n,i)
{
if(a[i]>1)q[++top]=a[i];
ww=ww*a[i];
if(ww>s){putl(fac[n+m]);return 0;}
}
sort(q+1,q+1+top);
rep(1,top,i)
{
if(q[i]==q[i-1])++w[sum],++i;
if(i<=top)c[++sum]=q[i],++w[sum];
}
p[sum]=1;
fep(sum-1,1,i)p[i]=p[i+1]*(w[i]+1);
dfs(1);//整理状态
rep(1,m,i)get(b[i]),++vis[min(b[i],s+1)],++h[b[i]];
rep(1,s+1,i)vis[i]+=vis[i-1];
f[s][tot]=fac[n+m]*inv[n+m-(vis[s+1]-vis[s])-(n-top)]%mod;
fep(s,0,i)
{
//if(i==0)cout<<"www"<<endl;
fep(tot,0,j)
{
if(!f[i][j])continue;
//枚举要取模的数字.
rep(1,i,k)
{
if(!h[k])continue;
//当前还有数字为 v[j]+vis[i]-1
//剩余有效数字为 v[j]+vis[i%k]
f[i%k][j]=(f[i%k][j]+h[k]*f[i][j]%mod*fac[v[j]+vis[i]-1]%mod*inv[v[j]+vis[i%k]]%mod)%mod;
}
rep(1,sum,k)//枚举要除以的数字.
{
if(g[j][k])
{
//当前还有数字为 v[j]-1+vis[i]
//剩余有效数字为 v[j]-1+vis[i/c[k]]
f[i/c[k]][j-p[k]]=(f[i/c[k]][j-p[k]]+g[j][k]*f[i][j]%mod*fac[v[j]-1+vis[i]]%mod*inv[v[j]-1+vis[i/c[k]]]%mod)%mod;
}
}
}
}
/*fep(s,0,i)
{
cout<<i<<' '<<"www"<<' ';
fep(tot,0,j)
cout<<f[i][j]<<' ';
cout<<endl;
}*/
putl(f[0][0]);
return 0;
}