zoukankan      html  css  js  c++  java
  • 2014百度之星复赛解题报告:The Patterns

    The Patterns
    时间限制: 5s  内存限制: 65536K

    问题描述:
    对于一个1到n的全排列Q,我们定义Q对应的字符串SQ,其中

    C497-4004-1.jpg
    例如对于n=5,Q=32154, SQ=DDUD。
    本任务为给定一个仅包含字符’U’与’D’长度为m的模式串P以及一个正整数n,求解1到n的任意全排列中模式串出现次数的期望值。例如某个SQ=UUU,P=UU,则P出现次数为2次。
    例如n=3,P=U,则1到n的所有全排列方案对应的模式串P出现次数分别为
      
    Q
      
                               SQ
    P出现次数
    123
    UU
    2
    132
    UD
    1
    213
    DU
    1
    231
    UD
    1
    312
    DU
    1
    321
    DD
    0
    则1到n的任意全排列中模式串出现次数的期望值
    c9c99608-b685-475b-8d7f-32d67dbf5182.JPG
    为了避免浮点数精度误差,请输出 ac3665fd-20ea-4b6d-8a63-5860c86936d3.JPG ,其中mod为取模操作,具体定义以及运算规则参见:链接地址

    输入
    输入数据第一行为一个整数T1 <= T <= 3333),表示有 T 组测试数据。
    下面T组数据,每组数据第一行包含2个正整数n, m,接下来一行包含一个字符串P(仅包含字符’U’与’D’)
    数据规模:1 <= m <= 1000       m<n<=1000000

    输出
    对于第k组数据,第一行输出Case #k:,第二行输出 ac3665fd-20ea-4b6d-8a63-5860c86936d3.JPG 

    样例输入
    5
    4 3
    UUU
    4 2
    UU
    10 8
    UUUUDDDD
    2 1
    U
    2 1
    D

    样例输出
    Case #1:
    1
    Case #2:
    8
    Case #3:
    1400
    Case #4:
    1
    Case #5:
    1


    解题报告:

    首先计算n=m+1的情况下,1到n的所有全排列中能匹配P的次数。令其为A,则此时期望为
    ac93e9fe-e553-4bfe-be69-73a04fa66f83.JPG
    令事件X_i表示在某个排列Q的第i个元素开始,之后的m+1个元素符合模式串P。则
    dcebc18c-c164-4ecc-b4e2-b13db57de15d.JPG
    根据期望的线性
    304d7fcc-97dc-49e4-8c39-f7e346992b3e.JPG
    d806382d-8cdf-4acf-96de-d4d54282da38.JPG
    因此只需要求解得到A即可得到答案。
    计算A采用动态规划算法
    f[i,j] 表示前 i 个数字,最后一个数字所在前i个数字中的排名为j (排名从1开始)
    则有
    f[1,1] = 1
    for i = 2..m + 1
      for j = 1..i                        
                       if p[i-2] == 'U'
                                         f[j]= f[i-1][j-1]+f[i-1][j-2]+…+f[i-1][1];
                       else
                                         f[j]= f[i-1][j]+f[i-1][j+1]…f[i-1][i-1];
    时间复杂度为O(m^3)
    而通过部分和优化可以优化到O(m^2)
    解题代码:
    #include <functional>
    #include <algorithm>
    #include <iostream>
    #include <fstream>
    #include <sstream>
    #include <iomanip>
    #include <numeric>
    #include <cstring>
    #include <climits>
    #include <cassert>
    #include <cstdio>
    #include <string>
    #include <vector>
    #include <bitset>
    #include <queue>
    #include <stack>
    #include <cmath>
    #include <ctime>
    #include <list>
    #include <set>
    #include <map>
    
    using namespace std;
    typedef long long LL;
    
    const int P = (int)1e9 + 7 ;
    
    const int MAXN = 1234;
    
    int count( char a[], char b[]) {
            int ret = 0;
            int rem = strlen(a);
            int m = strlen(b);
            
            for(int i = 0; a; ++ i, -- rem) if(rem >= m){
                    bool ok = 1;
                    for(int j = 0; b[j]; ++ j) {
                            if(a[i+j] != b[j]) {
                                    ok = 0;
                                    break;
                            }
                    }
                    if(ok) ret ++ ;
            }
            return ret;
    }
    
    int a[ MAXN ];
    LL f[ MAXN ][ MAXN ] , g[ MAXN ][ MAXN ];
    
    void inc( LL &a, LL b) {
            b%=P;
            if(b<0) b+=P;
            a += b;
            if(a>=P) a-= P;
    }
    
    LL dp( int m, char p[]){
            
            f[1][1] = 1 ;
            g[1][0] = 0;g[1][1] = 1;
            
            for(int i = 2; i <= m + 1; ++ i) {
                    g[0]=0;
                    for(int j = 1; j <= i; ++ j) {
                            if( p[i-2] == 'U') {
                                    f[j] = g[i-1][j-1];
                            }else {
                                    f[j] = ((g[i-1][i-1] - g[i-1][j-1])%P+P)%P;
                            }
                            g[j] = (g[j-1] + f[j])%P;
                    }
            }
            LL ans = 0;
            for(int i = 1; i <= m + 1; ++ i) inc( ans , f[m+1]);
            return ans;
    }
    
    LL bf(int n, int m, char p[]){
            char s[MAXN];
            s[n-1]=0;
            LL ans = 0;
            
            for(int i = 0; i < n; ++ i) a=i;
            do{
                    for(int i = 0; i < n-1 ; ++ i)
                            s = (a<a[i+1]?'U':'D');
                    ans += count( s , p ) ;
            }while(std::next_permutation(a,a+n));
            
            return ans;
    }
    
    LL bf_solve( int n, int m, char p[]) {
            LL _one = bf(m+1,m,p) * (n-m);
            for(int i = m+2; i <= n; ++ i) _one *= i ;
            return _one;
    }
    
    LL my_solve( int n, int m, char p[]) {
            LL _one = dp(m,p) * ((LL)n-m)%P;
            for(int i = m+2; i <= n; ++ i) _one =_one* i%P ;
            return _one;
    }
    
    void bf_check(){
            int n, m;
            char p[MAXN];
            for(n = 2; n <= 9; ++ n) {
                    for(m = 1; m < n; ++ m) {
                            p[m]=0;
                            for(int s = 0; s < (1<<m); ++ s) {
                                    for(int i = 0; i < m; ++ i) p=(s&(1<<i))?'U':'D';
                                    cout << n <<" " << m <<" " << p << endl;
                                    LL _a = bf( n, m, p ) ;
                                    LL _b = my_solve(n,m,p);
                                    cout << _a << endl;
                                    if(_a == _b) {
                                            static int cas = 0; ++ cas;
                                            cout <<"correct @" << cas << endl;
                                    }else {
                                            cout << "error!" << endl;
                                            return;
                                    }
                            }
                    }
            }
    }
    
    char p[ MAXN ];
    int n, m ;
    
    int main() {
            //bf_check();
            int T;
            int K = 1;
        cin >> T;
            while(T -- ) {
                    scanf("%d%d%s", &n, &m, p);
                    printf ("Case #%d:
    %d
    " , K++, (int) my_solve(n,m,p) );
            }
            return 0;
    }
    


  • 相关阅读:
    Android开发笔记(十八)——Toast
    20199303 2019-2020-2 《网络攻防实践》综合实践
    20199303 2019-2020-2 《网络攻防实践》第12周作业
    20199303 2019-2020-2 《网络攻防实践》第10周作业
    20199303 2019-2020-2 《网络攻防实践》第8周作业
    20199303 2019-2020-2 《网络攻防实践》第7周作业
    20199303 2019-2020-2 《网络攻防实践》第6周作业
    20199303 2019-2020-2 《网络攻防实践》第5周作业
    20199303 2019-2020-2 实践三网络嗅探与协议分析实践
    Deleting comments in c or java code by awk scripts
  • 原文地址:https://www.cnblogs.com/hosealeo/p/4190494.html
Copyright © 2011-2022 走看看