波动数列

原题链接

思路分析:
我们可以将每一次操作封装成 P = ( + a , − b ) P=(+a,-b) P=(+a,b) ,那么对于每一种满足条件的数列均有 x x x x + P 1 x+P_1 x+P1 x + P 1 + P 2 x+P_1+P_2 x+P1+P2 … \ldots x + P 1 + P 2 + … + P n − 1 x+P_1+P_2+\ldots+P_{n-1} x+P1+P2++Pn1
S = x + x + P 1 + x + P 1 + P 2 + … + x + P 1 + P 2 + … + P n − 1 S=x+x+P_1+x+P_1+P_2+\ldots+x+P_1+P_2+\ldots+P_{n-1} S=x+x+P1+x+P1+P2++x+P1+P2++Pn1,整理后等价于 S = n ∗ x + ( n − 1 ) ∗ P 1 + … + P n − 1 S=n*x+(n-1)*P_1+\ldots+P_{n-1} S=nx+(n1)P1++Pn1,观察式子 S − [ ( n − 1 ) ∗ P 1 + … + P n − 1 ] n = x \frac{S-[(n-1)*P_1+\ldots+P_{n-1}]}{n}=x nS[(n1)P1++Pn1]=x,由于题面中要求每一项都为整数,即分子 S − [ ( n − 1 ) ∗ P 1 + … + P n − 1 ] S-[(n-1)*P_1+\ldots+P_{n-1}] S[(n1)P1++Pn1]是分母 n n n的整数倍,即 S S S ( n − 1 ) ∗ P 1 + … + P n − 1 (n-1)*P_1+\ldots+P_{n-1} (n1)P1++Pn1 两者在 m o d mod mod n n n的情况下余数相同。所以我们只需要知道 ( n − 1 ) ∗ P 1 + … + P n − 1 (n-1)*P_1+\ldots+P_{n-1} (n1)P1++Pn1 S S S同余有多少种方案,便可求得答案。
d p [ i ] [ j ] dp[i][j] dp[i][j]为只考虑前 i i i项, ( n − 1 ) ∗ P 1 + … + ( n − i ) P i (n-1)*P_1+\ldots+(n-i)P_i (n1)P1++(ni)Pi m o d mod mod n n n的余数为 j j j方案数
( n − 1 ) ∗ P 1 + … + ( n − i ) P i = = j ( m o d   n ) (n-1)*P_1+\ldots+(n-i)P_i == j (mod\,n) (n1)P1++(ni)Pi==j(modn),对于第 i i i项而言,便有 ( n − 1 ) ∗ P 1 + … + ( n − i + 1 ) P i − 1 = = j − ( n − i ) ∗ P i (n-1)*P_1+\ldots+(n-i+1)P_{i-1}== j-(n-i)*P_i (n1)P1++(ni+1)Pi1==j(ni)Pi,根据 P = ( + a , − b ) P=(+a,-b) P=(+a,b),代入后推导出
d p [ i ] [ j ] = d p [ i − 1 ] [ j − ( n − i ) ∗ a ] + d p [ i − 1 ] [ j + ( n − i ) ∗ b ] dp[i][j]=dp[i-1][j-(n-i)*a]+dp[i-1][j+(n-i)*b] dp[i][j]=dp[i1][j(ni)a]+dp[i1][j+(ni)b],由于第一项为 x x x P 1 + P 2 + … + P n − 1 P_1+P_2+\ldots+P_{n-1} P1+P2++Pn1仅有 n − 1 n-1 n1项,所以最终答案为 d p [ n − 1 ] [ S ( m o d   n ) ] dp[n-1][S(mod \,n)] dp[n1][S(modn)]
初始化为 d p [ 0 ] [ 0 ] = 1 dp[0][0]=1 dp[0][0]=1,注意 m o d   n mod\,n modn要取正余数。

C o d e : Code: Code:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include 
using namespace std;
#define MaxN 1010
//#define MOD 998244353
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define endl '\n'
#define LL long long
#define PII pair
#define rint register int 
#define ULL unsigned long long
const int MOD=100000007;
//int days[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
//int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
template<class T> inline void read(T& x){
    x=0;int f=0;char ch=getchar();
    while( !isdigit(ch) ) f|=( ch == '-' ) , ch=getchar();
    while( isdigit(ch) )  x = ( x<<1 ) + ( x<<3 ) + ( ch^48 ) , ch=getchar();
    x = f ? -x : x;
}
template<class T> inline void print(T x){
	if ( x < 0 ) { putchar('-'); x = -x; }
	if ( x >= 10 ) print( x / 10 );
	putchar(x % 10 + '0');
}
int dp[MaxN][MaxN];
int mod(int a,int b){
	return (a%b+b)%b;
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int n,s,a,b;
	cin>>n>>s>>a>>b;
	dp[0][0]=1;
	for(int i=1; i<=n; i++){
		for(int j=0; j<n; j++){
			dp[i][j]=(dp[i-1][ mod(j-(n-i)*a,n)] +dp[i-1][ mod(j+(n-i)*b,n) ])%MOD;
		}
	}
	cout<<dp[n-1][mod(s,n)];
	return 0; 
}

你可能感兴趣的:(题解)