jzoj3424。[シミュレーション]画家NOIP2013

説明

ヘクターはたくましい画家であり、非常に思考のように= =
さて、寺は、これらの柱の長老たちによって要求される1からNラベルに直線上に配置されたN個の柱は、塗料の新鮮なコートを塗るます持っています。ヘクター浴槽がK異なる塗色を有し、塗料はちょうどI CIピラーをバケツペイント、及びでき、C1 + C2 + C3 ... CK = N( 即ち、N塗装柱がちょうどすべてのペイントを実行します)。にもかかわらずヘクターの長老は、隣接する列の同じ色をしませ必要です。
ヘクターはないだけで、すぐにペイントし始めたが、そのようなどのように多くのペイントプログラム、の合計としていくつかの奇妙な質問に、熟考し始めていなかったと考えたいですか?
すぐヘクターとしてペイントを開始するためには、できるだけ早く彼に答えを教えてください。

入力

正の整数Tの最初の行は、テストデータのセット表す
試験データの各セットのために:
行1:正の整数K
2行目:私は、ペイントバケットの列の数は塗装することができ、Kは正の整数でありますCI。

出力

入力データの各セットは、出力ラインプログラムスタッコMOD十億七の数を表す整数ため。

サンプル入力

3
3
1 2 3 4
5
2 2 2 2 2
10
1 1 2 2 3 3 4 4 5 5

サンプル出力

10
39480
85937576

データ制約

30%N≤10、T≤5
50%N≤15、T≤5
80%K≤15、Ci≤5、T≤500
100%K≤15、Ci≤6、T≤2000

問題の解決策

余談では
数日、私はまた、試験中に見たこの質問を言って。
その時間がないという考えで、行きたくありませんでした。
今日は突然、質問は非常に簡単です見つける、という考えを持っていた、見ました。
長い時間のためのチューニングは、サンプルの上に、結果TLE50を支払う。
なぜ?私は配列にゲームのF *3万100オープンを入れたとき。そのため
その後たびのmemsetは約2000、成功裏に爆発しました。

DPを考えてみましょう(と言って暴力がポイントを獲得するためによくないです)
私たちは、各顔料を得るために従ってください。
その後、顔料が追加された、唯一の我々は、現在の顔料の相対的な位置を検討する必要があり、顔料、染料列に考慮されていない必要がある、それを成し遂げる必要があります。
ababbd:現在の顔料である場合、その意味
の方法である3つのC顔料を追加:cacbabcbdを
我々は設定\(F _ {[I] } \) 溶液からなる電流I顔料の前にシーケンスを表しています。
しかし、十分な1次元。要求の対象は、隣接同色ないからです。
だから我々は現在の色と同じ色の目の前に満たすために、現在のj番目の位置の1次元表現の合計をより多くを支払います。
ちょっとした魔法に転送します。
実際には、各転送は、元の配列に挿入された新しいカラーボールをkと等価です。
この方法は、挿入された-
各インサートは、同じ2つのボールの間に挿入することが可能である、2つの異なるボールの間に挿入されてもよいです。
したがって、2つの同一のボールの間に挿入されたp個のボールで、Qは、二つの非同一の間にボールに挿入ボールを持っています。
:答えは\(C_J C_ {^ P * J +のSUM-Q 1} ^ \)
だけでなく、後者の二つでボール上記他のボールを有していてもよいです。
これは、m個の異なるプログラム・ボックスに入れN個の同一のボールの数に相当します。
プログラム番号は、\(+ C_ {N-M} 1-N- ^ {} \) インターポーザの原理を使用して)
と答えが\(C_ {K-1} ^ {KPQ} \)

標準プロセス

#include <iostream>
#include <cstdio>
#include <cstring>
#include <map>
using namespace std;

int maxn=32768,mo=1000000007;
int n,t;
int k[16];
long long f[100][100],mi[16],c[100][100],sum[32768],len[32768];

long long qsm(long long a,long long b)
{
    long long t=1;
    long long y=a;
    while (b>0)
    {
        if (b%2==1) t=(t*y)%mo;
        y=(y*y)%mo;
        b=b/2; 
    }
    return t;
}

int main()
{
    freopen("color.in","r",stdin);
    for (int i=0;i<=100;i++)
    {
        c[i][0]=1;
        for (int j=1;j<=i;j++)
        {
            c[i][j]=(c[i-1][j-1]+c[i-1][j])%mo;
        }
    }
    
    mi[0]=1;
    for (int i=1;i<=15;i++)
    {
        mi[i]=mi[i-1]*2;
    }
    scanf("%d",&t);
    while (t>0)
    {
        t--;
        scanf("%d",&n);
        for (int i=1;i<=n;i++)
        {
            scanf("%d",&k[i]);
        }
        memset(f,0,sizeof(f));
        memset(sum,0,sizeof(sum));
        memset(len,0,sizeof(len));
        f[0][0]=1;
            for (int i=1;i<=n;i++)
            {
                    if (i==1)
                    {
                        f[i][k[i]-1]=1;
                        sum[i]=k[i];
                        len[i]=1;   
                    }
                    else
                    {
                        for (int j=0;j<=sum[i-1];j++) 
                        {
                            if (f[i-1][j]>0)
                            { 
                                for (int p=0;p<=min(k[i],j);p++)
                                {
                                    for (int q=0;q<=k[i]-p;q++)
                                    {
                                        if (q+p>=1)
                                        {
                                            f[i][j-p+k[i]-p-q]+=(f[i-1][j]*c[j][p]*c[sum[i-1]-j+1][q]*c[k[i]-1][k[i]-p-q])%mo;
                                        }
                                    }
                                }
                            }
                        }
                        sum[i]=sum[i-1]+k[i];
                        len[i]=len[i-1]+1;
                    }
                
            }
        printf("%lld\n",(f[n][0])%mo);
    }
}

おすすめ

転載: www.cnblogs.com/RainbowCrown/p/11285013.html