計數基礎題目選做
阿新 • • 發佈:2020-08-11
只是基礎題目
T1
首先直接當成有 \(n\) 個白球做
這題目轉移還是比較套路的
\(f_{i,j}\) 表示 \(i\) 個白球,\(j\) 個顏色的方案數
轉移直接分為兩種情況:
直接新增一個白球和新增一種顏色
新增白球直接新增即可,即
f[i][j]=add(f[i][j],f[i-1][j]);
然後直接找空位組合數新增就好了,即
f[i][j]=add(f[i][j],f[i][j-1]*(n-j+1)%mod*C(n*k-i-1-(j-1)*(k-1),k-2)%mod);
關於為啥後面的是 \(k-2?\)
首先剩下了 \(k-1\) 個帶顏色的,然後欽定第一個位置是當前顏色,否則會記重
最後答案 \(f_{n,n}\)
#include<bits/stdc++.h> using namespace std; #define int long long #define For(i,a,b) for(register int i=a;i<=b;++i) namespace yspm{ inline int read() { int res=0,f=1; char k; while(!isdigit(k=getchar())) if(k=='-') f=-1; while(isdigit(k)) res=res*10+k-'0',k=getchar(); return res*f; } const int mod=1e9+7,N=4e6+10; int fac[N],inv[N],n,k,f[2010][2010]; inline int ksm(int x,int y) { int res=1; for(;y;y>>=1,x=x*x%mod) if(y&1) res=res*x%mod; return res; } inline int C(int n,int m){return fac[n]*inv[m]%mod*inv[n-m]%mod;} inline int add(int x,int y){return x+y>=mod?x+y-mod:x+y;} signed main() { fac[0]=1; inv[0]=1; For(i,1,N-1) fac[i]=fac[i-1]*i%mod; inv[N-1]=ksm(fac[N-1],mod-2); for(int i=N-2;i>=1;--i) inv[i]=inv[i+1]*(i+1)%mod; n=read(); k=read(); for(int i=0;i<=n;++i) f[i][0]=1; for(int i=1;i<=n;++i) { for(int j=1;j<=i;++j) { f[i][j]=add(f[i][j],f[i-1][j]); f[i][j]=add(f[i][j],f[i][j-1]*(n-j+1)%mod*C(n*k-i-1-(j-1)*(k-1),k-2)%mod); } } printf("%lld\n",f[n][n]); return 0; } } signed main(){return yspm::main();}
T2
這題數形結合好
考慮每個 \(i,j\) 的本質
是在一個平面直角座標系裡面從\((-a_i,-b_i)\) 到 \((a_j,b_j)\) 的方案
然後把所有的撒到一個平面直角座標系裡面然後做轉移
最後減掉那些自己轉移到自己的
#include<bits/stdc++.h> using namespace std; namespace yspm{ inline int read() { int res=0,f=1; char k; while(!isdigit(k=getchar())) if(k=='-') f=-1; while(isdigit(k)) res=res*10+k-'0',k=getchar(); return res*f; } const int M=2e5+10,N=4040,mod=1e9+7,s=2010; inline int add(int x,int y){return x+y>=mod?x+y-mod:x+y;} inline int del(int x,int y){return x-y<0?x-y+mod:x-y;} inline int id1(int x){return x+s;} inline int id2(int x){return s-x;} int a[M],b[M],f[N][N],inv[N],fac[N],ans,n; inline int C(int n,int m){return 1ll*fac[n]*inv[m]%mod*inv[n-m]%mod;} inline int ksm(int x,int y){int res=1; for(;y;y>>=1,x=1ll*x*x%mod) if(y&1) res=1ll*res*x%mod; return res;} signed main() { fac[0]=1; inv[0]=1; for(int i=1;i<N;++i) fac[i]=1ll*fac[i-1]*i%mod; inv[N-1]=ksm(fac[N-1],mod-2); for(int i=N-2;i>=1;--i) inv[i]=1ll*inv[i+1]*(i+1)%mod; n=read(); for(int i=1;i<=n;++i) { a[i]=read(),b[i]=read(); ++f[id2(a[i])][id2(b[i])]; } for(register int i=1;i<=s*2;++i) { for(register int j=1;j<=s*2;++j) { f[i][j]=add(f[i][j],f[i-1][j]); f[i][j]=add(f[i][j],f[i][j-1]); } } for(int i=1;i<=n;++i) ans=add(ans,f[id1(a[i])][id1(b[i])]),ans=del(ans,C(2*(a[i]+b[i]),2*a[i])); ans=1ll*ans*inv[2]%mod; cout<<ans<<endl; return 0; } } signed main(){return yspm::main();}
T3
[MtOI2018]情侶?給我燒了! 的加強版
先用高考數學的知識推出來這樣一個式子
\[\binom n i\times \binom n i\times 2^i \times i!\times g_{n-k} \]
\(g_i\) 表示 \(i\) 對情侶的錯排方案
然後推這個錯排的式子
按照普通錯排的做法
欽定第一排是錯誤的,這裡要乘上 \(2n\times (2n-2)\)
然後考慮剩下的方案
兩對情侶中剩下的兩個人不坐在一起,那麼是一個 \(g_{i-1}\)
反之則為 \(2\times(i-1)\times g_{i-2}\)
(選擇一個座位)
所以就可以 \(O(n)\) 預處理,然後可以 \(O(1)\) 回答
#include<bits/stdc++.h>
using namespace std;
#define For(i,a,b) for(register int i=a;i<=b;++i)
namespace yspm{
inline int read()
{
int res=0,f=1; char k;
while(!isdigit(k=getchar())) if(k=='-') f=-1;
while(isdigit(k)) res=res*10+k-'0',k=getchar();
return res*f;
}
const int mod=998244353,N=5e6+10;
int inv[N],fac[N],g[N],p[N],n,k;
inline int C(int n,int m){return 1ll*inv[m]*fac[n]%mod*inv[n-m]%mod;}
inline void work(int n,int k)
{
printf("%lld\n",1ll*C(n,k)*C(n,k)%mod*fac[k]%mod*p[k]%mod*g[n-k]%mod);
return ;
}
inline int ksm(int x,int y)
{
int res=1; for(;y;y>>=1,x=1ll*x*x%mod) if(y&1) res=1ll*res*x%mod;
return res;
}
signed main()
{
fac[0]=inv[0]=p[0]=1; g[0]=1;
For(i,1,N-1) fac[i]=1ll*fac[i-1]*i%mod,p[i]=1ll*p[i-1]*2%mod;
For(i,2,N-1) g[i]=1ll*2*i%mod*(2*i-2)%mod*((1ll*2*(i-1)%mod*g[i-2]%mod+g[i-1])%mod)%mod;
inv[N-1]=ksm(fac[N-1],mod-2); for(int i=N-2;i>=1;--i) inv[i]=1ll*inv[i+1]*(i+1)%mod;
int T=read();
while(T--)
{
n=read();
for(int i=0;i<=n;++i) work(n,i);
}
return 0;
}
}
signed main(){return yspm::main();}
程式碼粘的是 \(Luogu\) 普通版的