[SCOI2010] 生成字符串
阿新 • • 發佈:2018-10-04
cst () pan algo cor std str define namespace
zzk的互測題真毒瘤,三道題在洛谷上都是紫題......
而且T1是集訓隊真題,T2是NOI真題,T3是省選真題,難度貌似是遞減......
這道題是T3。
洛谷 P1641 傳送門
考試的時候是打表做的,30分的很顯然了,n2能推出來。
f[i][j]=f[i][j-1]+f[i-1][j](i<=j),f[0][0]=1。
然後我感覺這個遞推式的結構有點像楊輝三角,就打了個表。
發現f(n,m)=C(n+m,n)-C(n+m,n+1),於是就當場切掉了這道題。
當然打表找規律肯定不是正解。
正解是把這個問題轉化為另一種問題。
從(0,0)走到(n+m,n-m),x坐標為‘1‘和‘0‘的和,y坐標為‘1‘和‘0‘的差。
每次只能向右上或右下走。
右上(x++,y++)就是選了‘1‘,右下反之。
所以不考慮限制,所有情況是C(n+m,n)(n+m步裏有n個選擇‘1‘的步)。
限制是‘1‘>=‘0‘ , ‘1‘-‘0‘>=‘0‘-‘0‘
所以y>=0
也就是說,所有走到y=-1的都不合法。
而從(0,0)走到y=-1的都可以對稱成從(0,-2)走到y=-1。
所以不合法方案數為C(n+m,n+1)
最終求得答案就是f(n,m)=C(n+m,n)-C(n+m,n+1)。
也有用卡特蘭數的解法,我不會。
註意要用線性篩逆元求組合數(不過別的方法貌似也成)。
1 #include<cstdio> 2#include<cstring> 3 #include<algorithm> 4 #define mod 20100403 5 #define ll long long 6 using namespace std; 7 8 ll n,m; 9 ll mul[2000005],inv[2000005]; 10 11 ll c(ll x,ll y) 12 { 13 return (((mul[x]*inv[x-y])%mod)*inv[y])%mod; 14 } 15 16 int main() 17 { 18 scanf("%lld%lld",&n,&m);19 mul[0]=mul[1]=inv[0]=inv[1]=1; 20 ll tot=m+n; 21 for(ll i=2;i<=tot;i++)mul[i]=mul[i-1]*i%mod; 22 for(ll i=2;i<=tot;i++)inv[i]=(mod-mod/i)*inv[mod%i]%mod; 23 for(ll i=2;i<=tot;i++)inv[i]=inv[i]*inv[i-1]%mod; 24 ll ans=((c(tot,n)-c(tot,n+1))%mod+mod)%mod; 25 printf("%lld\n",ans); 26 return 0; 27 }
[SCOI2010] 生成字符串