• BNUOJ 34985 Elegant String 2014北京邀请赛E题 矩阵快速幂


    题目链接:http://acm.bnu.edu.cn/bnuoj/problem_show.php?pid=34985

    题目大意:问n长度的串用0~k的数字去填,有多少个串保证任意子串中不包含0~k的某一个全排列

    邀请赛上A的较多的一道题,比赛的时候死活想不出,回来之后突然就想通了,简直..... = =!

    解题思路:

    对于所有串我们都只考虑末尾最多有多少位能构成全排列的一部分(用l来表示),即最多有多少位不重复的数字出现,将问题转化为求末尾最多有k位能构成全排列的串的总数量

    假设k为5,有一个串……0023,不难发现l=3

    我们以这个串出发在之后添上数字,假如我们添的是0、2、3中的一个:

      0: ……00230 (l=3)

      2: ……00232 (l=2)

      3: ……00233 (l=1)

    假如是l长度中没有出现过的数字

      则构成新串 ……00231 ……00234  ……00235 l=4

    最后可以得到规律:总长度为n串中 l=m的串的数量 x1 得到 总长度为n+1的串中 l=(1,2,……,m)的串

             总长度为n串中 l=m的串的数量 x(k-m+2) 得到 总长度为n+1的串中 l=m+1的串

    用mar[i][j]来表示由l=j的串得到l=i的串所以

    mar可以表示为(以k=5为例)

    1  1  1  1  1

    5  1  1  1  1

    0  4  1  1  1

    0  0  3  1  1

    0  0  0  2  1

    通过该矩阵我们可以由长度为n的串数量可以推出长度为n+1的串的数量:

    于是我们可以通过长度1的串最终得到总长度为n的串,  n=1时只有l最多为1 总数为 k+1

    快速幂求得该矩阵的(n-1)次幂,该矩阵的第一列相加乘(k+1)即为最终结果

     1 #include <cmath>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <iostream>
     5 #include <algorithm>
     6 using namespace std;
     7 #define FFF 20140518
     8 struct node{
     9     long long mar[15][15];
    10 }sor;
    11 void init(int k)
    12 {
    13     memset(sor.mar,0,sizeof(sor.mar));
    14     for(int i=1;i<=k;i++)
    15     {
    16         for(int j=i;j<=k;j++)
    17         {
    18             sor.mar[i][j]=1;
    19         }
    20         if(i>1)
    21         {
    22             sor.mar[i][i-1]=k-i+2;
    23         }
    24     }
    25 }
    26 node marMulti(node a,node b,int k)
    27 {
    28     node ret;
    29     memset(ret.mar,0,sizeof(ret.mar));
    30     for(int i=1;i<=k;i++)
    31     {
    32         for(int j=1;j<=k;j++)
    33         {
    34             for(int l=1;l<=k;l++)
    35             {
    36                 ret.mar[i][j]+=(a.mar[i][l]*b.mar[l][j])%FFF;
    37                 ret.mar[i][j]%=FFF;
    38             }
    39         }
    40     }
    41     return ret;
    42 }
    43 node matrixPow(long long x,int k)
    44 {
    45     node now=sor;
    46     node ret;
    47     memset(ret.mar,0,sizeof(ret.mar));
    48     for(int i=1;i<=k;i++)
    49         ret.mar[i][i]=1;
    50     while(x)
    51     {
    52         if(x%2==1)
    53             ret=marMulti(now,ret,k);
    54         x/=2;
    55         now=marMulti(now,now,k);
    56     }
    57     return ret;
    58 }
    59 void print(node sor,int k)
    60 {
    61     for(int i=1;i<=k;i++)
    62     {
    63         for(int j=1;j<=k;j++)
    64         {
    65             cout<<sor.mar[i][j]<<' ';
    66         }
    67         cout<<endl;
    68     }
    69 }
    70 int main()
    71 {
    72     int keng,k,Case=1;
    73     long long n;
    74     scanf("%d",&keng);
    75     while(keng--)
    76     {
    77         scanf("%lld%d",&n,&k);
    78         init(k);
    79         node ret=matrixPow(n-1,k);
    80         int ans=0;
    81         // print(sor,k);
    82         // print(ret,k);
    83         for(int i=1;i<=k;i++)
    84         {
    85             ans+=(ret.mar[i][1]*(k+1))%FFF;
    86             ans%=FFF;
    87         }
    88         printf("Case #%d: %d
    ",Case++,ans);
    89     }
    90     return 0;
    91 }
    View Code
  • 相关阅读:
    k6负载测试学习知识
    52条SQL语句性能优化策略(转)
    JVM学习
    jsonp劫持
    Airtest API精讲之keyevent()
    Airtest API精讲之Android自定义手势
    Airtest API精讲之text()
    Airtest之调用其他脚本——using()如何使用
    Airtest API精讲之wait(),exists()
    Airtest API精讲之报告日志log()
  • 原文地址:https://www.cnblogs.com/wuwing/p/3754808.html
Copyright © 2020-2023  润新知