hdu6030 经典矩阵快速幂+递推关系

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6030

题目要求给出一个长度为n的串,要求这个串中任意长度为素数的连续序列中r的数量多于或者等于b,我们不难得出只要长度为2或者3的序列都满足这个条件就能得出整个序列满足题目要求的条件,简单的证明如下:如果是长度为偶数的素数,那一定只有2,满足最小性条件,如果是大小为奇数的素数代表的连续区间,则这个奇数可以分解成若干个2和3,的短序列,由于序列条件的可加性。所以整个序列也是满足条件的。对于递推关系,可以考虑局部的转移规则,因为长度为2和3的区间需要考虑,所以我们每次递推的时候就考虑2->3长度的转移过程。用an表示末两位为rr的方案数,bn表示末位为rb的方案数,cn表示末位为br的方案数,所以总共的方案数有an+bn+cn,初值为a2=b2=c2=1,有关系 an=an-1+cn-1,bn=an-1,cn=bn-1.根据关系构造矩阵即可在O(logn)时间内求出an+bn+cn;

代码如下:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef unsigned int ui;
 4 typedef long long ll;
 5 typedef unsigned long long ull;
 6 #define pf printf
 7 #define mem(a,b) memset(a,b,sizeof(a))
 8 #define prime1 1e9+7
 9 #define prime2 1e9+9
10 #define pi 3.14159265
11 #define lson l,mid,rt<<1
12 #define rson mid+1,r,rt<<1|1
13 #define scand(x) scanf("%llf",&x) 
14 #define f(i,a,b) for(int i=a;i<=b;i++)
15 #define scan(a) scanf("%d",&a)
16 #define mp(a,b) make_pair((a),(b))
17 #define P pair<int,int>
18 #define dbg(args) cout<<#args<<":"<<args<<endl;
19 #define inf 0x7ffffff
20 inline int read(){
21     int ans=0,w=1;
22     char ch=getchar();
23     while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
24     while(isdigit(ch))ans=(ans<<3)+(ans<<1)+ch-'0',ch=getchar();
25     return ans*w;
26 }
27 int t;
28 ll n;
29 const int maxn=3;
30 const ll mod=1e9+7;
31 struct mat{
32     ll a[maxn][maxn];
33     mat()
34     {
35         f(i,0,maxn-1)
36             f(j,0,maxn-1)
37                 a[i][j]=0;
38     }
39     mat operator * (const mat &x)const 
40     {
41         mat c;
42         f(i,0,maxn-1)
43             f(j,0,maxn-1)
44                 f(k,0,maxn-1)
45                 {
46                     c.a[i][j]=(c.a[i][j]+a[i][k]*x.a[k][j])%mod;        
47                  } 
48                 return c;
49     }
50 };
51 mat pow_mod(mat A,ll k)
52 {
53     mat ans;
54     ans.a[0][0]=ans.a[1][1]=ans.a[2][2]=1;
55     while(k)
56     {
57         if(k&1)ans=ans*A;
58         A=A*A;
59         k>>=1;
60     }
61     return ans;
62 }
63 int main()
64 {
65     //freopen("input.txt","r",stdin);
66     //freopen("output.txt","w",stdout);
67     std::ios::sync_with_stdio(false);
68     t=read();
69     mat A;
70     A.a[0][0]=A.a[0][2]=A.a[1][0]=A.a[2][1]=1;
71     while(t--)
72     {
73         scanf("%lld",&n);
74         if(n==2)
75         {
76             pf("3\n");
77             continue;
78         }
79         ll ans=0;
80         mat tmp=pow_mod(A,n-2);
81         f(i,0,maxn-1)
82             f(j,0,maxn-1)
83             {
84                 ans=(ans+tmp.a[i][j])%mod;
85             }
86             pf("%lld\n",ans);
87     }
88 } 

猜你喜欢

转载自www.cnblogs.com/randy-lo/p/12726383.html