1. 程式人生 > >HDU 6327 2018HDU多校賽 第三場 Random Sequence(概率期望dp+數論)

HDU 6327 2018HDU多校賽 第三場 Random Sequence(概率期望dp+數論)

Problem I. Random Sequence

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


 

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 :

∏i=1n−3v[gcd(ai,ai+1,ai+2,ai+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≤ai≤m) , 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

大致題意:給你一個數列,裡面的數字要麼是0,要麼是1~m中的一個數字。你需要隨機的把這些0替換成1~m中的任意一個,然後再計算著整個數列的權值。權值定義為\prod_{i=1}^{n-3} v[\gcd(a_i,a_{i+1},a_{i+2},a_{i+3})],現在問你最後權值的期望。

由於這個v陣列是輸入的,也就是說沒有什麼性質,所以這個權值的表示式也不能用數論的知識推出什麼結論。因此我們考慮暴力的dp。我們令dp[i][j][k][l]表示當前計算到第i位,且a[i]取j,a[i-1]取k,a[i-2]取l時的期望的分子。那麼,從這個狀態出發,列舉a[i+1]的數值,就看求出著四個數字的gcd,對應轉移過去即可。如此一來,時間複雜度就是O(N^4*M)。顯然是不可以接受的。

接下來,我們考慮進行優化。我們注意到,如果a[i]取2,a[i-1]取4和6都是一樣的,也就是說,每一維我們根本沒有必要從1..m的列舉,我們考慮列舉對應的gcd即可。由此,我們重新定義dp陣列,dp[i][j][k][l]表示當前計算到第i位,且a[i]取j,gcd(a[i],a[i-1])取k,gcd(k,a[i-2])取l時的期望的分子。但是這麼表示,列舉起來還是很複雜,於是我們考慮提前預處理所有合法的狀態,然後把每一個狀態對應一個數字,如此陣列就變成一個二維的dp[i][j]表示當前處理到第i個數字,然後最近三個數字的狀態是狀態j的期望的分子。

然後轉移目標就是下一位,然後對應修改三個gcd的值,轉移的量就是四個數字的gcd與dp[i][j]的乘積。這樣總的複雜度就是O(N*M*tot+M^3) 其中tot表示合法的狀態數目,M^3位初始化的複雜度。最後的結論是,合法狀態數不超過1471個。具體實現見程式碼:

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define IO ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define mod 1000000007
#define N 110
#define LL long long


using namespace std;

int dp[N][1500],gcd[N][N],id[N][N][N];
struct node{int x,y,z;} st[1500];
int n,m,tot,v[N],a[N],inv[N];

void init()
{
    tot=0; inv[1]=1;
    for(int i=2;i<N;i++)
        inv[i]=1LL*(mod-mod/i)*inv[mod%i]%mod;
    for(int i=1;i<=100;i++)
        for(int j=1;j<=i;j++)
            gcd[i][j]=gcd[j][i]=__gcd(i,j);
    for(int i=1;i<=100;i++)
        for(int j=1;j<=i;j++)
            if (i%j==0)
            for(int k=1;k<=j;k++)
            {
                if (j%k) continue;
                st[++tot]=node{i,j,k};
                id[i][j][k]=tot;
            }
}

int main()
{
    IO; init();
    int T; cin>>T;
    while(T--)
    {
        cin>>n>>m;
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++) cin>>a[i];
        for(int i=1;i<=m;i++) cin>>v[i];
        for(int i=1;i<=m;i++)
            if (!a[3]||a[3]==i)
            for(int j=1;j<=m;j++)
                if (!a[2]||a[2]==j)
                for(int k=1;k<=m;k++)
                {
                    if (a[1]&&a[1]!=k) continue;
                    int y=gcd[i][j],z=gcd[y][k];
                    int nxt=id[i][y][z];
                    dp[3][nxt]++;
                }
        for(int j=3;j<n;j++)
        {
            for(int i=1;i<=tot;i++)
            {
                if (!dp[j][i]) continue;
                int x=st[i].x,y=st[i].y,z=st[i].z;
                for(int k=1;k<=m;k++)
                {
                    if (a[j+1]&&k!=a[j+1]) continue;
                    int yy=gcd[k][x],zz=gcd[k][y];
                    int nxt=id[k][yy][zz];
                    dp[j+1][nxt]+=1LL*v[gcd[k][z]]*dp[j][i]%mod;
                    if (dp[j+1][nxt]>=mod) dp[j+1][nxt]-=mod;
                }
            }
        }
        LL ans=0;
        for(int i=1;i<=tot;i++)
        {
            ans+=dp[n][i];
            if (ans>=mod) ans-=mod;
        }
        for(int i=1;i<=n;i++)
            if (!a[i]) ans=ans*inv[m]%mod;
        cout<<ans<<endl;
    }
    return 0;
}

相關推薦

HDU 6327 2018HDU Random Sequence概率期望dp+數論

Problem I. Random Sequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others) Total Submissio

HDU 6350 2018HDU Always Online圖論 + 並查集 + 組合計數

          大致題意:給你一個仙人掌圖,讓你計算:。 根據去年多校賽某一道題的經驗,很多仙人掌圖的問題,其實可以轉化為樹的問題。所以我們同樣考慮,如果這是一棵樹的話如何去做。注意到表示式裡面的flow(i,j)表示從i到j的最小割或最大流,而在樹上的最小

HDU 6340 2018HDU Delightful Formulas莫比烏斯反演+伯努利數+NTT+積性

大致題意:給你k和m,還有n分解質因子之後的質因子及其對應的指數,讓你求 。 首先,這種含有gcd的式子,第一步肯定是進行莫比烏斯反演,這裡由於前面好幾篇都由類似的反演形式,所以我就不展開了,直接就得出反演之後的結果:              

HDU 6338 2018HDU Depth-First Search組合數學+平衡樹/pbds

大致題意:給你一個dfs序列B和一棵樹,現在讓你在這個樹上隨機選擇一個點,然後按照隨機的dfs順序走。問你最後能走出幾個dfs序列,是得該dfs序列字典序小於給定的dfs序B。 首先,我們考慮一棵樹有根樹他的dfs序有多少種。我們可以這麼考慮,對於任意點x,

HDU 6428 2018HDU Calculate莫比烏斯反演 + 積性 + 線性篩

題意簡單粗暴,讓你求  。 與gcd有關,一般來說都是要上莫比烏斯來反演一下了。具體來說,我們先來推一些式子:                                      

HDU 6416 2018HDU Rikka with Seamdp + 字首和優化

大致題意:給你一個n*m的01矩陣,現在要讓你每一行和每一列都去掉一個數字,而且要求相鄰兩行之間去掉數字的位置的絕對值要小於等於k。現在問你刪除之後的矩形最多有幾種。 首先,我們一行一行考慮,對於同一行,顯然是看有多少個塊,有多少個塊就有多少個方案。然後對於

HDU9 HDU 4965Fast Matrix Calculation【矩陣運算+數學小知識】

stdin amp line you stream [] nbsp content ans 難度上。,,確實。。。不算難 問題是有個矩陣運算的優化 題目是說給個N*K的矩陣A給個K*N的矩陣B(1<=N<=1000 && 1=<K<

HDU 6063 RXD and math+(快速冪+聯賽

RXD and math Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)

2017 訓練 HDU 6063 RXD and math

打表找規律然後發現是n的k次冪 然後快速冪,實現的時候有一些地方會溢位,可以快速乘或者先進行取模運算 #include <bits/stdc++.h> using namespace st

HDU 6314 2018HDU第二 Matrix容斥原理+組合計數

Matrix Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 332768/332768 K (Java/Others) Total Submission(s): 445    Accepted Submiss

牛客網訓練 C - Shuffle CardsSplay / rope

str spl shuf 鏈接 contest www size targe strong 鏈接: https://www.nowcoder.com/acm/contest/141/C 題意: 牛客網多校訓練第三場 C - Shuffle Cards(Splay /

2017年 1005 FFF at Valentine縮點+拓撲排序

其實縮點很容易想到,就是不怎麼會用拓撲排序所以一直卡著判斷這個地方。 程式碼如下: #include <stdio.h> #include <string.h> #include <vector> #include <s

2017年 1006 Senior Pandijkstra套路題

這道題有很多解法,我是按照題解的做法寫了一遍。 題意:給出一個有向圖,然後有k個點,問這k個點兩兩之間的最短距離的最小值是多少。 解法:題解是把k個點按照每個點二進位制位的不同分成兩個集合,然後求一次多源最短路。由於最大的數是1e5,所以也就到個。。。2^17的樣子?由於

聯合

1003 The Goddess Of The Moon 題意:如果字串存在某個字首與另一個字串的字尾相同,則這兩個字串匹配,求n種字串連成m個字串的連線方式。 dp[i][j]=∑<k,j>匹配dp[i−1][k],dp[i][j]是指前i個串

2018牛客網暑期ACM訓練 J-Distance to Work

思路分析: 板子題,簡單多邊形和圓面積交 + 二分 程式碼如下: #include <cstdio> #include <algorithm> #include <cstring> #include <cmath>

hdu6434 杭電 1009 I題 count

Problem I. Count Problem Description Multiple query, for each n, you need to get n i-1 ∑ ∑ [gcd(i + j, i - j) = 1] i=1 j=1 Input On th

2018-2019賽季聯合新生訓練(2018/12/8)補題題解

感慨 得複習回溯和dfs了。。。 A 變形蟲(語法基礎) 程式碼 #include <bits/stdc++.h> using namespace std; map<int,int> num; int main() { ios::sync_with_stdio(0);

Contest1593 - 2018-2019賽季聯合新生訓練部分題解

H 10255 自然數無序拆分   H 傳送門 題幹: 題目描述 美羊羊給喜羊羊和沸羊羊出了一道難題,說誰能先做出來,我就獎勵給他我自己做的一樣禮物。沸羊羊這下可樂了,於是馬上答應立刻做出來,喜羊羊見狀,當然也不甘示弱,向沸羊羊發起了挑戰。 可是這道題

2018-2019賽季聯合新生訓練題解和補題

本次成績 第44名(銅牌) 雖然都是銅牌,但是這次比上次強多了2333 這次感覺水題比較多啊,但是還是有幾個不會做的,你們懂那種使勁做一道兩道題就是做不出來的感覺嗎!!!簡直要死,這次比賽和上次比賽間隔太短了,可能導致用腦過度了(滑稽)下面開始我們愉快的題解和補題環節吧!(要是我英語演講能這

2018-2019賽季聯合新生訓練

問題 A: 變形蟲時間限制: 1 Sec 記憶體限制: 128 MB 提交: 667 解決: 473 題目描述Bessie是一隻變形蟲,一開始它的體重是A。在地板上從左往右依次放著N塊蛋糕,第i塊蛋糕的重量是Wi。變形蟲從左邊爬到右邊,每次遇到一塊蛋糕,如果蛋糕的重量恰好等於變形蟲當前的重量