1. 程式人生 > >[Codeforces301E][DP]Yaroslav and Arrangements

[Codeforces301E][DP]Yaroslav and Arrangements

翻譯

如果一個數列相鄰兩項之差的絕對值均為 1(我們認為首項和末項也相 鄰),並且首項是數列中最小的元素之一,那麼我們稱之為良好數列。 如果一個數列單調不降且長度在 1 到 n 之間,數列中每個數的值在 1 到 m 之間,且重排後能得到至少 1 個至多 k 個良好數列,那麼我們稱之為優秀數列。 給出 n、m、k,求優秀數列的個數。 答案對 1000000007 取模

題解

這題有點東西… 把首項看成1,破環成鏈,a[n+1]=1 如果在最大值為i的情況下,最後乘一個mi+1m-i+1就好了 我們考慮如何設計狀態 首先你至少要知道當前這個數列能組成多少個良好數列 從小往大加數 比如兩個1之間如果有空格,他們之間至少要加一個2 所以我們再加入一個狀態,當前必須要加多少個數 啊別忘了記錄當前加入了多少個數 列舉當前加入的數的數量 設他為T 設至少要加K個數 顯然,我們會有T-K個組合兩兩之間是空格 所以 f

[i][j][k]>f[i+1][j+T][TK]f[i][j][k]->f[i+1][j+T][T-K] 等等,還沒轉移方案數 其實就相當於T個球要放入K個箱子中不允許有空 那不就是f[i][j][k][l]>f[i+1][j+T][TK][lCT1K1]f[i][j][k][l]->f[i+1][j+T][T-K][l*C_{T-1}^{K-1}] 然後列舉到一個最大值記錄答案即可

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<ctime>
#include<map>
#define LL long long
#define mp(x,y) make_pair(x,y)
#define mod 1000000007
using namespace std;
inline
int read() { int f=1,x=0;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } inline void write(int x) { if(x<0)putchar('-'),x=-x; if(x>9)write(x/10); putchar(x%10+'0'); } inline void pr1(int x){write(x);printf(" ");} inline void pr2(int x){write(x);puts("");} int n,m,K; int C[105][105]; int f[2][105][105][105];//當前最大值 已經加了多少個數 還必須要加多少個數 方案數 void ad(int &x,int y){x+=y;if(x>=mod)x-=mod;} int main() { n=read();m=read();K=read(); if(n==1)return puts("0"),0; C[0][0]=1; for(int i=1;i<=100;i++) for(int j=0;j<=100;j++) { C[i][j]=j?C[i-1][j]+C[i-1][j-1]:C[i-1][j]; if(C[i][j]>K)C[i][j]=K+1; } n++; int now=0,ans=0;f[now][0][1][1]=1; for(int i=0;i<=m;i++) { now^=1;int num=0; if(i) { for(int j=2;j<=n;j++) for(int k=1;k<=K;k++) ad(num,f[now^1][j][0][k]); ad(ans,(LL)num*(m-i+1)%mod); } memset(f[now],0,sizeof(f[now])); for(int j=0;j<=n;j++) for(int k=1;k<=n;k++) for(int l=1;l<=K;l++) if(f[now^1][j][k][l]) for(int t=k;t+j<=n;t++) ad(f[now][j+t][t-k][min(K+1,l*C[t-1][k-1])],f[now^1][j][k][l]); } pr2(ans); return 0; }