P2107. 变化的序列
题目描述
有如下序列 4 1 3 0 2 4 ...
在这个序列中,你会发现,后面的一项 比前面的多2或者少3。
求:长度为n, 总和为s, 且后面一项比前面的多a,或者少b的整数序列有多少种?
输入格式
四个整数 n s a b,含义如前面说述。
输出格式
四个整数 n s a b,含义如前面说述。
样例
输入数据 1
4 10 2 3
输出数据 1
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。
读懂题之后会感觉整个序列的首项特别重要,就设为\(x\),每一次操作是\(y\),(\(y=a\) \(or\) \(y=-b\))
则序列为\(\{x,x+y_1,x+y_1+y_2,...,x+y_1+y_2+...+y_{n-1}\}\)
则序列的和为
\[nx+(n-1)y1+(n-2)y2+(n-3)y3+...+y_{n-1}=S
\]
令\(nx\)后面那一坨为\(k\)
则可以得到 \(nx=S-k\)
即可得到\(k\, \equiv \,S\, \, (\ mod \ n)\)
就可以推出其对应的状态转移方程式:
\[\left\{\begin{matrix} & f[i+1][\ getmod(\ j+a(i+1),n)\ ]+=f[i][j]\\ & f[i+1][\ getmod(\ j-b(i+1),n)\ ]+=f[i][j]\end{matrix}\right.
\]
最后写初始化:
\[f[1][getmod(a,n)]=f[1][getmod(-b,n)]=1
\]
最后是代码:
#include <bits/stdc++.h>
using namespace std;
const int N=2e3,mod=100000007;
int n,a,b,s;
int getmod(int k,int p){
return (k%p+p)%p;
}
int f[N][N];
signed main(){
ios::sync_with_stdio(0);
cin>>n>>s>>a>>b;
f[1][getmod(a,n)]=f[1][getmod(-b,n)]=1;
for(int i=1;i<=n;i++){
for(int j=0;j<=n-1;j++){
f[i][j]=getmod(f[i][j],mod);
f[i+1][getmod(j+a*(i+1),n)]+=f[i][j];
f[i+1][getmod(j-b*(i+1),n)]+=f[i][j];
//cout<<setw(4)<<f[i][j];
}//cout<<endl;
}
cout<<f[n-1][getmod(s,n)]%mod;
return 0;
}

浙公网安备 33010602011771号