zoukankan      html  css  js  c++  java
  • 考研路茫茫――单词情结 HDU

    背单词,始终是复习英语的重要环节。在荒废了3年大学生涯后,Lele也终于要开始背单词了。``
    一天,Lele在某本单词书上看到了一个根据词根来背单词的方法。比如"ab",放在单词前一般表示"相反,变坏,离去"等。

    于是Lele想,如果背了N个词根,那这些词根到底会不会在单词里出现呢。更确切的描述是:长度不超过L,只由小写字母组成的,至少包含一个词根的单词,一共可能有多少个呢?这里就不考虑单词是否有实际意义。

    比如一共有2个词根 aa 和 ab ,则可能存在104个长度不超过3的单词,分别为
    (2个) aa,ab,
    (26个)aaa,aab,aac...aaz,
    (26个)aba,abb,abc...abz,
    (25个)baa,caa,daa...zaa,
    (25个)bab,cab,dab...zab。

    这个只是很小的情况。而对于其他复杂点的情况,Lele实在是数不出来了,现在就请你帮帮他。

    Input
    本题目包含多组数据,请处理到文件结束。
    每组数据占两行。
    第一行有两个正整数N和L。(0<N<6,0<L<2^31)
    第二行有N个词根,每个词根仅由小写字母组成,长度不超过5。两个词根中间用一个空格分隔开。
    Output
    对于每组数据,请在一行里输出一共可能的单词数目。
    由于结果可能非常巨大,你只需要输出单词总数模2^64的值。
    Sample Input
    2 3
    aa ab
    1 2
    a
    Sample Output
    104
    52

    思路:首先看到模数是 (2^{64}), 很明显要用ULL定义数据,实现自动取模,这题其实和POJ - 2778差不多,不过那题只用求长度为 m 的, 这题要求长度 1~m 的和, 由于这题求的是包含模式串的,所以我们求出不包含的数量再用总数减去即可得到结果。重点在于如何快速求出 1 ~ m 的和, 其实只要再得出的矩阵后加上一列全为1的一列就可以了,具体原理不做解释。

    #include <cstdio>
    #include <algorithm>
    #include <queue>
    #include <string>
    #include <string.h>
    using namespace std;
    typedef unsigned long long ULL;
    const int maxn = 40;
    const int mod = 100000;
    int nex[maxn][26], Exits[maxn], fail[maxn], last[maxn], cnt;
    struct mat
    {
        ULL a[maxn][maxn];
        mat operator * (const mat m){
            mat res;
            memset(res.a, 0, sizeof(res.a));
            for(int i = 0; i <= cnt; i++){
                for(int j = 0; j <= cnt; j++){
                    for(int k = 0; k <= cnt; k++){
                        res.a[i][j] += a[i][k] * m.a[k][j];
                    }
                }
            }
            return res;
        }
    } unit, matrix;
    
    void init_unit(){
        for(int i = 0; i <= cnt; i++){
            unit.a[i][i] = 1;
        }
    }
    
    mat pow_mat(long long n){
        init_unit();
        mat res = unit;
        while(n){
            if(n & 1){
                res = res * matrix;
            }
            n >>= 1;
            matrix = matrix * matrix;
        }
        return res;
    }
    
    void insert(char *s, int len){
        int p = 0;
        for(int i = 0; i < len; i++){
            int x = s[i] - 'a';
            if(nex[p][x] == 0){
                memset(nex[cnt], 0, sizeof(nex[cnt]));
                Exits[cnt] = 0;
                last[cnt] = 0;
                fail[cnt] = 0;
                nex[p][x] = cnt++;
            }
            p = nex[p][x];
        }
        Exits[p] = 1;
    } 
    
    queue<int> que;
    void Build(){
        for(int i = 0; i < 26; i++){
            if(nex[0][i]) que.push(nex[0][i]);
        }
        while(que.size()){
            int p = que.front();
            que.pop();
            for(int i = 0; i < 26; i++){
                int u = nex[p][i];
                if(u){
                    fail[u] = nex[fail[p]][i];
                    last[u] = Exits[fail[u]] ? fail[u] : last[fail[u]];
                    que.push(u);
                } else {
                    nex[p][i] = nex[fail[p]][i];
                }
            }
        }
    }
    
    void init(){
        memset(matrix.a, 0, sizeof(matrix.a));
        for(int i = 0; i < cnt; i++){
            if(!Exits[i] && !last[i]) {
                for(int j = 0; j < 26; j++){
                    int u = nex[i][j];
                    if(!Exits[u] && !last[u]){
                        matrix.a[i][u]++;
                    }
                }
            }
        }
        for(int i = 0; i <= cnt; i++){
            matrix.a[i][cnt] = 1;
        }
    }
    
    ULL qpow(ULL n){
        ULL a;
        a = 26;
        ULL res = 1;
        while(n){
            if(n & 1){
                res *= a;
            }
            a *= a;
            n >>= 1;
        }
        return res;
    }
    int main(int argc, char const *argv[])
    {
        int n;
        long long m;
        while(~scanf("%d%I64d", &n, &m)){
            memset(nex[0], 0, sizeof(nex[0]));
            cnt = 1;
            char s[20];
            for(int i = 1; i <= n; i++){
                scanf("%s", s);
                insert(s, strlen(s));
            }
            Build();
            init();
            mat res = pow_mat(m + 1);
            ULL ans = res.a[0][cnt] - 1;
    
            memset(matrix.a, 0, sizeof(matrix.a));
            matrix.a[0][0] = 26;
            matrix.a[0][1] = matrix.a[1][1] = 1;
            cnt = 2;
            res = pow_mat(m + 1);
            ULL ans2 = res.a[0][1] - 1;
            printf("%I64u
    ", ans2 - ans);
        }
        return 0;
    }
  • 相关阅读:
    [SSRS] Use Enum values in filter expressions Dynamics 365 Finance and Operation
    Power shell deploy all SSRS report d365 FO
    display method in Dynamics 365 FO
    How To Debug Dynamics 365 Finance and Operation
    Computed columns and virtual fields in data entities Dynamics 365
    Azure DevOps for Power Platform Build Pipeline
    Create readonly entities that expose financial dimensions Dynamics 365
    Dataentity call stack dynamics 365
    Dynamics 365 FO extension
    Use singletenant servertoserver authentication PowerApps
  • 原文地址:https://www.cnblogs.com/PCCCCC/p/13235976.html
Copyright © 2011-2022 走看看