CodeForces 466 D.Increase Sequence(组合数学+dp)
2018-01-09 19:51
471 查看
Description
给出一个长度为n的序列ai,每次操作可以将一个区间的值全部加一,但是不能有两个操作的端点值相同,问有多少种方案可以使得所有数字变成h
Input
第一行输入两个整数n,h,之后输入n个整数ai(1≤n,h≤2000,0≤ai≤2000)
Output
输出方案数,结果模109+7
Sample Input
3 2
1 1 1
Sample Output
4
Solution
以左括号表示操作区间左端点,右括号表示操作区间右端点,那么一个位置不能出现两个以及上的左括号或右括号,故一个位置只有四种情况,不放括号,放一个左括号,放一个右括号,放一个左括号放一个右括号
用dp[i][j]表示前i个位置还没匹配的左括号比还没匹配的右括号多j个且使得a1=a2=...=ai=h的方案数
1.第i个位置不放括号,有dp[i][j]+=dp[i−1][j]
2.第i个位置放左括号,有dp[i][j]+=dp[i−1][j−1]
3.第i个位置放右括号,有dp[i][j]+=(j+1)⋅dp[i−1][j+1],乘上j+1是因为要给当前放的这个右括号匹配上左括号
4.第i个位置放左右括号,有dp[i][j]+=(j+1)⋅dp[i−1][j],乘上j+1同样是因为要给当前这个右括号匹配上左括号
注意对于1,2情况,ai位置相当于被加了j,故需要ai+j=h该步才可以转移过去,同样的,对于3,4情况,ai位置加了j+1,故需要ai+j+1=h,最后dp[n][0]即为答案
Code
给出一个长度为n的序列ai,每次操作可以将一个区间的值全部加一,但是不能有两个操作的端点值相同,问有多少种方案可以使得所有数字变成h
Input
第一行输入两个整数n,h,之后输入n个整数ai(1≤n,h≤2000,0≤ai≤2000)
Output
输出方案数,结果模109+7
Sample Input
3 2
1 1 1
Sample Output
4
Solution
以左括号表示操作区间左端点,右括号表示操作区间右端点,那么一个位置不能出现两个以及上的左括号或右括号,故一个位置只有四种情况,不放括号,放一个左括号,放一个右括号,放一个左括号放一个右括号
用dp[i][j]表示前i个位置还没匹配的左括号比还没匹配的右括号多j个且使得a1=a2=...=ai=h的方案数
1.第i个位置不放括号,有dp[i][j]+=dp[i−1][j]
2.第i个位置放左括号,有dp[i][j]+=dp[i−1][j−1]
3.第i个位置放右括号,有dp[i][j]+=(j+1)⋅dp[i−1][j+1],乘上j+1是因为要给当前放的这个右括号匹配上左括号
4.第i个位置放左右括号,有dp[i][j]+=(j+1)⋅dp[i−1][j],乘上j+1同样是因为要给当前这个右括号匹配上左括号
注意对于1,2情况,ai位置相当于被加了j,故需要ai+j=h该步才可以转移过去,同样的,对于3,4情况,ai位置加了j+1,故需要ai+j+1=h,最后dp[n][0]即为答案
Code
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<cmath> #include<vector> #include<queue> #include<map> #include<set> #include<ctime> using namespace std; typedef long long ll; typedef pair<int,int>P; const int INF=0x3f3f3f3f,maxn=2005; #define mod 1000000007 int n,h,a[maxn],dp[maxn][maxn]; void add(int &x,int y) { x=x+y>=mod?x+y-mod:x+y; } int main() { while(~scanf("%d%d",&n,&h)) { for(int i=1;i<=n;i++)scanf("%d",&a[i]); memset(dp,0,sizeof(dp)); if(a[1]==h||a[1]==h-1)dp[1][0]=1; if(a[1]==h-1)dp[1][1]=1; for(int i=2;i<=n;i++) for(int j=max(0,h-a[i]-1);j<=min(h-a[i],i);j++) if(a[i]+j==h) { add(dp[i][j],dp[i-1][j]); if(j)add(dp[i][j],dp[i-1][j-1]); } else if(a[i]+j+1==h) add(dp[i][j],(ll)(j+1)*(dp[i-1][j+1]+dp[i-1][j])%mod); printf("%d\n",dp [0]); } return 0; }
相关文章推荐
- Codeforces 466 E. Information Graph
- Codeforces 466 D. Increase Sequence
- Codeforces 466 E. Information Graph
- codeforces 466 C Number of Ways
- Codeforces 466 A. Cheap Travel
- Codeforces 466 C. Number of Ways
- codeforces 466-C. Number of Ways(前缀和+尺取)
- Codeforces 466 B. Wonder Room
- codeforces 768D Jon and Orbs (概率dp)
- CodeForces - 811A
- CodeForces 913 E. Logical Expression
- codeforces 296C
- Codeforces 549G. Happy Line 贪心
- [CodeForces 543A]Writing Code[DP]
- codeforces 707D Persistent Bookcase
- CodeForces - 361A B - Levko and Table 思维
- Dreamoon and Sets CodeForces - 476D(规律,思路题)
- CodeForces - 330D Biridian Forest(逆向bfs)
- codeforces 192
- Codeforces 12D Ball (线段树)