円形のぬりえ

円形のぬりえ

N 0、M 1は、周方向に隣接配置され、同一円周上のすべての数字は、すべてのプログラムの重みの和に破壊チェーンリングを求め、組成定義セグメント長の積の右セグメントに配置されると、\ (N、M \のLeq 5000 \)

ソリューション

区間分割に関連する問題のため、考え配列のない直接計数を行い、我々は仮定することができる\(Fを[I] [J] \)明らかセクションに分割された第1のI要素(同一)と重みJ、用

\ [[K] [J-1](IK)F F [I] [J] = \ sum_ {k = 0} ^ {I-1} \]

この式は、\(O(N ^ 3)\) そして考える最適化、の二つの方法

アクトワン:

\ [F [I] [J] = iが\ sum_ {k = 0} ^ {I-1} [K] [J-1] F - \ sum_ {k = 0} ^ {I-1} KF [K ] [J-1] \]

だから我々はちょうどメンテナンス\(F [k]は[J -1] \) と\(KF [k]は[J -1] \) プレフィックスとすることができ、表現の最適化のために、通常は無関係分離しますアイテム、または出現回数を考慮する個々のひとつ。

アクトII:

\ [F [I] [J] = \ sum_ {k = 0} ^ {I-1} F [k]は[J-1](IK)= \]
\ [\ sum_ {k = 0} ^ {I -1} [K] [J-1](IK-1)F + \ sum_ {k = 0} ^ {I-1} [K] [J-1] F = \]
\ [[I-1 F ] [J] + F [I-1] [J-1] + [K] F \ sum_ {k = 0} ^ {I-1} [J-1] \]

限り、我々は維持するとして、\(F [k]は[J ] \)をk個のプレフィックスに、私は、個人的に法IIを好むことができます。

明らかに、セグメント0、セグメント番号1、それはプロパティ01のシーケンスと同じであるのでの列挙子セグメント\(\ sum_ {i = 1 } ^ {分(N、M)} [N] F [I ] \タイムズF [M] [I] \) に対応するセグメントの0リングの開始時に全て0の重み値であり、実際の意味と、任意の開始時にチェーンが、他の説明によれば、容易に乗じ知っ係数\((N-Mの+)/ Iが\) 係数Iは、単純な証明を与えることができません。

参照コード:

#include <iostream>
#include <cstdio>
#include <cstring>
#define il inline
#define ri register
#define ll long long
#define Size 5050
#define yyb 1000000007
using namespace std;
int dp[Size][Size],s[Size],iv[Size];
int main(){
    int n,m;iv[1]=1;
    for(int i(2);i<=5000;++i)iv[i]=-(ll)yyb/i*iv[yyb%i]%yyb;
    for(int i(1);i<=5000;++i)dp[i][1]=i;
    for(int i,j(2);j<=5000;++j){
        for(i=1;i<j;++i)s[i]=s[i-1]+dp[i][j-1];
        for(i=j;i<=5000;++i)
            dp[i][j]=(dp[i-1][j]+s[i-1])%yyb,
                s[i]=(s[i-1]+dp[i][j-1])%yyb;
    }
    while(scanf("%d%d",&n,&m)!=EOF){
        int ans(0);
        for(int i(1);i<=min(n,m);++i)
            ans=(ans+(ll)dp[n][i]*dp[m][i]%yyb*(n+m)%yyb*iv[i])%yyb;
        printf("%d\n",(ans+yyb)%yyb);
    }
    return 0;
}

おすすめ

転載: www.cnblogs.com/a1b3c7d9/p/11408935.html