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;
}