1. 程式人生 > >HDU 6327&&18多校訓練3I 【DP】

HDU 6327&&18多校訓練3I 【DP】

Problem I. Random Sequence

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 56    Accepted Submission(s): 13


 

Problem Description

There is a positive integer sequence a1,a2,...,an with some unknown positions, denoted by 0. Little Q will replace each 0 by a random integer within the range [1,m
] equiprobably. After that, he will calculate the value of this sequence using the following formula :            

\prod_{i=1}^{n-3}v[gcd(a[i],a[i+1],a[i+2],a[i+3])]


Little Q is wondering what is the expected value of this sequence. Please write a program to calculate the expected value.  

Input

The first line of the input contains an integer T

(1≤T≤10), denoting the number of test cases.
In each test case, there are 2 integers n,m(4≤n≤100,1≤m≤100) in the first line, denoting the length of the sequence and the bound of each number.
In the second line, there are n integers a1,a2,...,an(0≤aim), denoting the sequence.
In the third line, there are m
integers v1,v2,...vm(1≤vi≤109), denoting the array v.

 

Output

For each test case, print a single line containing an integer, denoting the expected value. If the answer is AB, please print C(0≤C<109+7) where AC×B(mod109+7).

 

Sample Input

2 6 8 4 8 8 4 6 5 10 20 30 40 50 60 70 80 4 3 0 0 0 0 3 2 4

 

Sample Output

8000 3

 

Source

題意:給定陣列a,如果ai為0則小明從1到m中隨機選擇一個數。求\prod_{i=1}^{n-3}v[gcd(a[i],a[i+1],a[i+2],a[i+3])]的期望值。

題解:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL MOD=1e9+7;
int p[110][110],a[110],l[110],r[110];
LL dp[2][101][101][101];
LL v[110];
vector<int> di[110];
LL pod(LL x,LL n,LL MOD)
{
    LL ret=1;
    while(n)
    {
        if(n&1)ret=ret*x%MOD;
        n>>=1;
        x=x*x%MOD;
    }
    return ret;
}
int main()
{
    for(int i=1; i<=100; i++)
        for(int j=1; j<=100; j++)
            p[i][j]=__gcd(i,j);
    for(int i=1; i<=100; i++)
        for(int j=i; j<=100; j+=i)
            di[j].push_back(i);
    int TA;
    scanf("%d",&TA);
    while(TA--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&a[i]);
            if(a[i]==0)
            {
                l[i]=1;
                r[i]=m;
            }
            else
            {
                l[i]=a[i];
                r[i]=a[i];
            }
        }

        for(int i=1; i<=m; i++)scanf("%lld",&v[i]);
        memset(dp,0,sizeof(dp));
        int w=0;
        for(int i=l[3]; i<=r[3]; i++)
        {
            for(int j=l[2]; j<=r[2]; j++)
            {
                for(int k=l[1]; k<=r[1]; k++)
                {
                    dp[w][i][p[i][j]][p[p[i][j]][k]]++;
                }
            }
        }
        for(int i=3; i<n; i++)
        {
            for(int x=1; x<=m; x++)
            {
                for(int y,yy=0; yy<di[x].size(); yy++)
                {
                    y=di[x][yy];
                    for(int z,zz=0; zz<di[y].size(); zz++)
                    {
                        z=di[y][zz];
                        if(dp[w][x][y][z]==0)continue;
                        for(int j=l[i+1]; j<=r[i+1]; j++)
                        {
                            (dp[w^1][j][p[j][x]][p[j][y]]+=(dp[w][x][y][z]*v[p[j][z]])%MOD)%=MOD;

                        }
                        dp[w][x][y][z]=0;

                    }
                }
            }
          
            w^=1;
        }
        LL ans=0;
        for(int x=1; x<=100; x++)
        {
            for(int y,yy=0; yy<di[x].size(); yy++)
            {
                y=di[x][yy];
                for(int z,zz=0; zz<di[y].size(); zz++)
                {
                    z=di[y][zz];
                    ans=(ans+dp[w][x][y][z])%MOD;
                }
            }
        }
        LL tem=pod(m,MOD-2,MOD);
        for(int i=1; i<=n; i++)
            if(a[i]==0)
                ans=ans*tem%MOD;
        printf("%lld\n",ans);
    }
}