Circular Coloring

Circular Coloring

The n 0, m 1 is a circumferentially arranged adjacent and all the numbers on the same circle is arranged in a right segment of the product of the composition defined segment length, asking broken chain ring to a sum of weights of all the programs and, \ (n-, m \ Leq 5000 \) .

solution

Because of problems related to the interval division, do not direct counting of the sequence considered, we may assume \ (F [i] [j] \) for the first i elements (identical) divided into sections and the weight j, clearly

\[f[i][j]=\sum_{k=0}^{i-1}f[k][j-1](i-k)\]

This equation is \ (O (n-^. 3) \) , then consider optimization, two methods

Act One:

\[f[i][j]=i\sum_{k=0}^{i-1}f[k][j-1]-\sum_{k=0}^{i-1}kf[k][j-1]\]

So we just maintenance \ (f [k] [j -1] \) and \ (kf [k] [j -1] \) prefix and can be, for optimization of expression, usually to separate unrelated item, or one of the individual to consider the number of occurrences.

Act II:

\[f[i][j]=\sum_{k=0}^{i-1}f[k][j-1](i-k)=\]
\[\sum_{k=0}^{i-1}f[k][j-1](i-k-1)+\sum_{k=0}^{i-1}f[k][j-1]=\]
\[f[i-1][j]+f[i-1][j-1]+\sum_{k=0}^{i-1}f[k][j-1]\]

So long as we maintain \ (f [k] [j ] \) on the k prefix and I can, personally prefer Act II.

Obviously segment 0 and segment number 1 is the same, it is a property 01 sequence, so enumerator segments for \ (\ sum_ {i = 1 } ^ {min (n, m)} f [n] [i ] \ Times F [m] [I] \) , the actual meaning that is all in weight value of 0 at the beginning of the 0 ring of segments corresponding to and, while the chain at an arbitrary beginning, according to other explanations, readily know multiplied by a coefficient \ ((n-m +) / I \) , the coefficient I can not give a simple proof.

Reference Code:

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

Guess you like

Origin www.cnblogs.com/a1b3c7d9/p/11408935.html