蓝桥 PREV-30 历届试题 波动数列 【动态规划】
历届试题 波动数列时间限制:1.0s 内存限制:256.0MB问题描述观察这个数列:
1 3 0 2 -1 1 -2 ...
这个数列中后一项总是比前一项增加2或者减少3。
栋栋对这种数列很好奇,他想知道长度为 n 和为 s 而且后一项总是比前一项增加a或者减少b的整数数列可能有多少种呢?输入格式输入的第一行包含四个整数 n s a b,含义如前面说述。输出格式输出一行,包含一个整数,表示满足条件的方案数。由于这个数很大,请输出方案数除以100000007的余数。样例输入4 10 2 3样例输出2样例说明这两个数列分别是2 4 1 3和7 4 1 -2。数据规模和约定对于10%的数据,1<=n<=5,0<=s<=5,1<=a,b<=5;
对于30%的数据,1<=n<=30,0<=s<=30,1<=a,b<=30;
对于50%的数据,1<=n<=50,0<=s<=50,1<=a,b<=50;
对于70%的数据,1<=n<=100,0<=s<=500,1<=a, b<=50;
对于100%的数据,1<=n<=1000,-1,000,000,000<=s<=1,000,000,000,1<=a, b<=1,000,000。
题目链接:
http://lx.lanqiao.cn/problem.page?gpid=T122
题目大意:
一个数列长度为n,每一项等于前一项+a或者-b,数列和为s,求数列的个数 mod 100000007。
题目思路:
【动态规划】
首先考虑如果全+a,数列和则会+a*(n-1)n/2,-b同理
即对于和s来说总共有(n-1)n/2次+或-操作。于是考虑如何将(n-1)n/2次操作分配给+a和-b。
容易想到这就是一个DP问题 f[i][j]表示前i个数,+a了j次的方案数。
第i个+a: f[i-1][j-i], 第i个-b: f[i-1][j]
最后枚举+a的个数为i的情况下,将数列和s补到+a-b之前的状态,看是否满足%n=0(即求首项为整数)
可行则答案加上当前的分配方案数。
f[i][j]可以化成1维
1 /**************************************************** 2 3 Author : Coolxxx 4 Copyright 2017 by Coolxxx. All rights reserved. 5 BLOG : http://blog.csdn.net/u010568270 6 7 ****************************************************/ 8 #include<bits/stdc++.h> 9 #pragma comment(linker,"/STACK:1024000000,1024000000") 10 #define abs(a) ((a)>0?(a):(-(a))) 11 #define lowbit(a) (a&(-a)) 12 #define sqr(a) ((a)*(a)) 13 #define mem(a,b) memset(a,b,sizeof(a)) 14 const double eps=1e-8; 15 const int J=10000; 16 const int MOD=100000007; 17 const int MAX=0x7f7f7f7f; 18 const double PI=3.14159265358979323; 19 const int N=1004; 20 using namespace std; 21 typedef long long LL; 22 double anss; 23 LL aans; 24 int cas,cass; 25 int n,m,lll,ans; 26 LL s,a,b; 27 LL f[N*N]; 28 int main() 29 { 30 #ifndef ONLINE_JUDGE 31 // freopen("1.txt","r",stdin); 32 // freopen("2.txt","w",stdout); 33 #endif 34 int i,j,k,l; 35 int x,y,z; 36 // for(scanf("%d",&cass);cass;cass--) 37 // for(scanf("%d",&cas),cass=1;cass<=cas;cass++) 38 // while(~scanf("%s",s)) 39 while(~scanf("%d",&n)) 40 { 41 mem(f,0); 42 cin>>s>>a>>b; 43 f[0]=1;aans=0; 44 for(i=1;i<n;i++) 45 for(j=i*(i+1)/2;j>=i;j--) 46 f[j]=(f[j]+f[j-i])%MOD; 47 for(i=0;i<=n*(n-1)/2;i++) 48 { 49 LL t=s-i*a+((n-1)*n/2-i)*b; 50 if(t%n==0)aans=(aans+f[i])%MOD; 51 } 52 cout<<aans<<endl; 53 } 54 return 0; 55 } 56 /* 57 // 58 59 // 60 */