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\n",Case++,ans);

89     }

90     return 0;

91 }
View Code

 

你可能感兴趣的:(String)