Counting Sequence

  When the analog cut off, I feel this question is very good. (Although T1 will not expect what took a twenty-five points messing around, T2 finally staged a string of dp, also opened last array of small ...... but finally the dog into the top five)

  Questions face Description:

  Construction of a N points directed graph G, no initial edge. Next construct a side length E sequence A, a sequence each edge are satisfied 1≤s, t≤N and s ≠ t directed edge (s, t), and the sequence of the sides different from each other . These edges in order to be added to G, each counting the number of strongly connected components of the current graph and recorded after the addition to obtain a new sequence of positive integers length E of B. If the sequence of the two sides of the same B obtained they are essentially the same as claimed.

  Will the different nature of the sequence of how many sides there are, as long as you find the answer to 10 ^ 9 + 7 result of modulo.

  Obviously can not run over and over again Tarjan (laughing cry)

  We first analyze the problem:

  First, we consider a legitimate sequence B, must be no increase in monotonous. We will consider a chain as a backbone graph, we added for each edge, we consider it is to continue to expand this chain, or even the casual side in the original chain on. So we designed a state of the conventional F [i] [j] denotes the front edges i, j number of programs are now strongly connected components.

  So it is clear that for some i and j is a relationship, not any pair i, j are legitimate.

  So we consider the wave:

  Suppose now that the sequence is divided into k sections B, equal to the size of each segment (with some waste side), then as applied on the basis of the side chain with at least k-1 item, then that edge up to the chain there i - k +1 bar.

  Setting Bi = j, j that is to say there are a strongly connected component, then the side chain apparently used a minimum of n - j Article (a ring, j - 1 outlier, n - j + 1 point on the ring , n - j + 1 the rings of the top, which has a reverse side).

  We should then obviously satisfy n - j <= i - k + 1, and more, that is to say for a pair i, j we must satisfy i + j> = n + k -1 job.

  This is the case whether lawfully received limit k. That is for a pair i, j, the corresponding situations are not legitimate, lawful situation i, j is a subset of all of its conditions.

  Then we will add a dimensional limit, F [i] [j] [k] i applied to the representative sides, has a strongly connected component j, k is divided into several program sections.

  Then we found that, since this is a simple graph, when the number of the strongly connected component is j, the number of edges is capped, at most (n - j + 1) * (n - 1) + (j - 1) * (j - 2) / 2.

  We must satisfy the condition i <= (n - j + 1) * (n - 1) + (j - 1) * (j - 2) / 2.

  Then f [i] [j] [k] of the transfer is very good, as long as consideration is whether the i th edge scrap to: f [i] [j] [k] + = f [i - 1] [h ] [k - 1] + f [i - 1] [j] [k].  

  By maintaining the prefix and as we put down to the complexity of the n- 3 , but obviously we still are not satisfied> /// <

  We observed that i + j> = n + k -1, found that i> = 2n when the always true, so we do not need the dimension of k, f [i] [j] will be able to transfer also same.

  That's it it! Of course, since the simulation time n is 100, then there is no need to transfer the two-dimensional, three-dimensional n . 4 is acceptable.

  Code:

  1. simulation code:

#include <iostream>
#include <cstdio>
#define maxn 102
#define mod 1000000007
using namespace std;
int dp[maxn * maxn][maxn][maxn];
int add(int x, int y)
{
    x += y;
    return x >= mod ? x - mod : x;
}
int main()
{
    int n;
    cin >> n;
    for (int i = n; i >= 0; -- i)
        dp[0][i][0] = 1;
    for (int e = 1; e <= n * (n - 1); ++ e)
    {
        int ans = 0;
        for (int v = 1; v <= n; ++ v)
            for (int m = 0; m < n; ++ m)
                if (e >= (n - v) + m && e <= (n - v + 1) * (n - 1) + (v - 1) * (v - 2) / 2)
                {
                    dp[e][v][m] = add(dp[e][v][m], (mod + dp[e - 1][v][m] - dp[e - 1][v + 1][m]) % mod);
                    dp[e][v][m] = add(dp[e][v][m], dp[e - 1][v + 1][m - 1]);
                    ans = add(ans, dp[e][v][m]);
                }
        for (int m = 0; m <= n; ++ m)
            for (int v = n - 1; v >= 0; -- v)
                dp[e][v][m] = add(dp[e][v][m], dp[e][v + 1][m]);
        printf("%d ",ans);
    }
    return 0;
}

  2. n <= 400 dimensional optimized code:

#include<cstdio>
#include<iostream>
#include<queue>
#include<algorithm>
#include<cmath>
#include<vector>
#include<cstring>
using namespace std;
#define mod 1000000007
const int maxn = 500;
int lim[maxn], f[2][maxn][maxn], sf[2][maxn][maxn], g[2][maxn], sg[2][maxn],ans[maxn*maxn];
int n;
int main()
{
    scanf("%d",&n);
    for (int i = 1; i <= n; i++)
        lim[i] = (n - i + 1) * (n - 1) + (i - 1) * (i - 2) / 2;
    f[1][n][1] = ans[1] = 1;
    for (int i = 1; i <= n; i++)
        sf[1][i][1] = 1;
    for (int i = 2; i <= min(n * (n - 1), n << 1); i++)
    {
        int op = i & 1;
        for (int j = 1; j <= n; j++)
            for (int k = 1; k <= n; k++)
                f[op][j][k] = 0;
        for (int j=1; j<=n; j++)
            if (i<=lim[j])
                for (int k = 1; k <= n; k++)
                     If (i + j> = n + k - 1 ) 
                        f [on] [j] [k] = (f [at ^ 1 ] [j] [k] + sf [at ^ 1 ] [j + 1 ] [k - 1 ])% mod;
        for ( int j = n; j> = 1 ; j-- )
             for ( int k = 1 ; k <= n; k ++ ) 
            { 
                sf [on] [j] [k] = (sf [on] [j + 1 ] [k] + f [on] [j] [k])% mod; 
                ans [i] = (ans [i] + f [on] [j] [k])% mod;
            }
    }
    for (int j = 1; j <= n; j++)
        for (int k = 1; k <= n; k++)
            g[0][j] = (g[0][j] + f[0][j][k]) % mod;
    for (int j = n; j >= 1; j--)
        sg[0][j] = (sg[0][j + 1] + g[0][j]) % mod;
    for (int i = (n << 1) + 1; i <= n * (n - 1); i++)
    {
        int op = i & 1;
        for (int j = 1; j <= n; j++)
            g[op][j] = 0;
        for (int j = 1; j <= n; j++)
            if (i <= lim[j])
                g[op][j] = sg[op ^ 1][j];
        for (int j = n; j >= 1; j--)
        {
            sg[op][j] = (sg[op][j + 1] + g[op][j]) % mod;
            ans[i] = (ans[i] + g[op][j]) % mod;
        }
    }
    for (int i = 1; i <= n * (n - 1); i++)
        printf("%d ", ans[i]);
    printf("\n");
    return 0;
}

 

  

Guess you like

Origin www.cnblogs.com/popo-black-cat/p/11122798.html
Recommended