AtCoder Grand Contest 013D: Piling Up 題解
阿新 • • 發佈:2019-03-28
情況 之前 include out fin fine del ons etc 黑黑 , 白白, 黑白,白黑
按照常規思路:
我們不妨設 f[i][j] 表示當前進行第i次操作, 還剩下 j 個白球(其實顏色沒影響)
所以對於每一個當前狀態則是可以有之前的狀態,通過上面列舉的四種操作得到
即
因為它要求的只是順序, 還在序列中的黑白球的數量並不重要!
所以求出所有的方案數之後,我們只需將 n=n-1 再跑一遍
然後用第一次的答案減去第二次的答案,就是真正的答案了. (想想為什麽)代碼
題意簡化:
[luogu] Piling Up
一開始有n個顏色為黑白的球,但不知道黑白色分別有多少,m次操作,每次先拿出一個球,再放入黑白球各一個,再拿出一個球,最後拿出的球按順序排列會形成一個顏色序列,求顏色序列有多少種
n,m小於等於3000 答案對1e9+7取膜
一些亂七八糟的東西
這個題還是 Power_Leo101 同學教我做的, 自己太弱了,完全不會
這是菊隊ppt裏推薦的題, 這個學期過了, 學長們就畢業了, 菊隊也不再會給我們講課了
雖然陳菊開學長講課的畫風毒瘤, ppt毒瘤
題解
對於每一次操作,其實是可以看成一次染色的,因為總數總是不變,而顏色卻會變化
所以對於每一次染色,即有四種情況: 嘿嘿
按照常規思路:
我們不妨設 f[i][j] 表示當前進行第i次操作, 還剩下 j 個白球
所以對於每一個當前狀態則是可以有之前的狀態,通過上面列舉的四種操作得到
即
if (j>0)
f[i][j] = f[i][j] + f[i-1][j] + f[i-1][j-1]; //是白白和白黑兩種情況
if (j<n)
f[i][j] = f[i][j] + f[i-1][j] + f[i-1][j+1]; //是黑白和黑黑兩種情況
但是
這連樣例都跑不過!!!
沒想到吧
這是為什麽呢???
再通過觀察, 可以發現題目要求的是取出的球的不同順序方案,而在我們的處理中有了很多重復的
所以求出所有的方案數之後,我們只需將 n=n-1 再跑一遍
然後用第一次的答案減去第二次的答案,就是真正的答案了. (想想為什麽)
代碼 (沒有註釋,不要槍斃我)
#include<bits/stdc++.h> using namespace std; #define re register #define ll long long #define get getchar() #define in inline #define db double #define mian main in int read() { int t=0; char ch=get; while(ch<'0' || ch>'9') ch=get; while (ch<='9' && ch>='0') t=t*10+ch-'0', ch=get; return t; } const int _=3010; const int mod=1e9+7; ll n,m,f[_][_]; int main() { n=read(),m=read(); for (re int i=0;i<=n;i++)f[0][i]=1; ll ans=0; for (re int i=1; i<=m; i++) for (re int j=0; j<=n; j++) { if(j>0) f[i][j]=(f[i][j]+f[i-1][j-1]+f[i-1][j])%mod; if(j<n) f[i][j]=(f[i][j]+f[i-1][j+1]+f[i-1][j])%mod; } for (re int i=0; i<=n; i++) ans=(ans+f[m][i])%mod; ll ans1=0; memset(f,0,sizeof(f)); for (re int i=0;i<=n-1;i++)f[0][i]=1; for (re int i=1; i<=m; i++) for (re int j=0; j<=n-1; j++) { if(j>0) f[i][j]=(f[i][j]+f[i-1][j-1]+f[i-1][j])%mod; if(j<n-1) f[i][j]=(f[i][j]+f[i-1][j+1]+f[i-1][j])%mod; } for (re int i=0; i<=n-1; i++) ans1=(ans1+f[m][i])%mod; cout<<((ans-ans1)+mod)%mod; }
嗯, 就這樣,這是蒟蒻的第一篇正式題解了
AtCoder Grand Contest 013D: Piling Up 題解