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;
}

posted @ 2025-05-24 11:46  shencheng4014  阅读(25)  评论(0)    收藏  举报