ブルーブリッジカップ - 変動シーケンス(動的計画+スクロール配列)

トピック:

ここに画像を挿入説明

入力と出力:

ここに画像を挿入説明

トピック分析:

最初必ずしもP = {-b}発現し、そして、最終になり、この操作に後ろXの数に基づいて、B操作をされた第1の数は、その後追加するため、Xであると仮定または減算:
バツ + バツ + P + バツ + 2 P + + バツ + n個 - 1 P = S X +(X + P)+(X + 2P)+ ... +(X +(N-1)P)= S
上式の変換は、約あります。 n個 バツ + ( 1 + 2 + 3 + . . . + n 1 ) P = s NX +(1 + 2 + 3 + ... + N-1)P = P
上記式総数Pのように、一定であることを示し、N(N-1)/及びXが、整数であるので
x = ( s n ( n 1 ) / 2 P ) / n X =(S - 、N(N-1)/ 2 * P)/ N

上記の説明によれば、我々はそれらの数、および範囲内の数議論することができ、[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;
}

公開された61元の記事 ウォン称賛7 ビュー3626

おすすめ

転載: blog.csdn.net/weixin_42469716/article/details/104894326