トピック:
入力と出力:
トピック分析:
最初必ずしもP = {-b}発現し、そして、最終になり、この操作に後ろXの数に基づいて、B操作をされた第1の数は、その後追加するため、Xであると仮定または減算:
上式の変換は、約あります。
上記式総数Pのように、一定であることを示し、N(N-1)/及びXが、整数であるので
上記の説明によれば、我々はそれらの数、および範囲内の数議論することができ、[0、N(N-1 )/ 2]、 動的プログラミングを分析するために使用することができる:
DP [I] i番目の要素のための[j]が以前に発現され、jは、次にプログラムの数は、以下の状況です。
- iがJよりも大きい場合、私による係数DPに[i] [j]は、DPから必然である[I-1] [j]が使用されるIすることができないと言うことである変換します
- jがIよりも大きい場合、i及び使用することができ、または使用しないので、私は、以下でJである場合、これ以下の変換がある:
。DP [I] [J] = DP [I-1]〜[J] + DP [I- 1 ] [JI]
上記の規則によれば、範囲は、jが0(N-1)Nであり、1からI N-1であるべきである/ 2、明らかに、あまりにも多くのメモリを占有し、次いで上記の式を観察するであろう、現在の状態だけ前の状態で見出されますあなたが解決スクロール配列を使用できるように、関連します。
コード・ショー:
#include <iostream>
#include <cstring>
#include <cstdio>
#define MOD 100000007
using namespace std;
const int MAXN = 1005;
long long dp[2][MAXN*MAXN];
long long n,s,a,b;
int main()
{
scanf("%lld%lld%lld%lld",&n,&s,&a,&b);
dp[0][0] = 1;
int flag = 0;
for(int i=1;i<n;++i)
{
flag = 1 - flag;
for(int j=0;j<=i*(i+1)/2;++j)
if(j < i)
dp[flag][j] = dp[1-flag][j];
else
dp[flag][j] = (dp[1-flag][j]%MOD + dp[1-flag][j-i]%MOD)%MOD;
}
long long ans,cnt = 0;
for(int i=0;i<=n*(n-1)/2;++i)
{
ans = s - i*a + (n*(n-1)/2-i)*b;
if(ans % n == 0)
cnt = (cnt%MOD+dp[flag][i]%MOD)%MOD;
}
printf("%lld\n",cnt);
return 0;
}