hdu 6030

题意: 给出红蓝两种,然后排成一个字符串,要求在每一个长度为素数的区间里面是的r(red)的数量不小与b(blue)的数量;

思路:想象当n为2的时候的情况是 rr,rb,br,三种情况,当n为3的时候相当于在后面添加一个b或者r,会发现形成rr的情况是前面rr和br的和,形成br的情况是前面的rb,而形成rb的情况是前面的rr,不能有前面的br形成rb,因为在素数为3的时候不能形成brb;

所以你会发现这个针对的素数只是2和3;

根据递推,设数组a[],b[],c[]分别为后面两个字母为rr,br,rb的字符串的数量,那么可以得到递推式:

a[i] = a[i - 1] + c[i - 1];b[i] = a[i - 1];c[i] = b[i - 1];

而题中要求的是所有的字符串,即s[n] = a[n] + b[n] + c[n];

可以得出s[i] = s[i - 1] + s[i - 3];

n的范围是10^18,那么只能用到矩阵快速幂:[si-3,si-2,si-1]*(0  0  1)=[si-2,si-1,si]

                              1  0  0

                              0  1  1

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int mod=1e9+7;
 5
 6 struct node{
 7    ll a[4][4];
 8 };
 9 int b[6];
10 node mat;
11
12
13 node jj(node p,node q){
14     node c;
15     memset(c.a,0,sizeof(c.a));
16     for(int k = 1; k <= 3; ++k) {
17         for(int i =1; i <=3; ++i) {
18             if(p.a[i][k] <= 0)  continue;
19             for(int j = 1; j <=3; ++j) {
20                 if(q.a[k][j] <= 0)    continue;
21                 c.a[i][j] = (c.a[i][j]+p.a[i][k] * q.a[k][j])%mod;
22             }
23         }
24     }
25     return c;
26 }
27    int t;
28 node hh(node p,ll k){
29    // cout<<t<<endl;
30     node c;
31     for(int i=1;i<=3;i++)
32         for(int j=1;j<=3;j++) c.a[i][j]=(i==j);
33     while(k){
34         if(k&1) c=jj(c,p);
35         k=k/2;
36         p=jj(p,p);
37     }
38
39     return c;
40 }
41
42 int main(){
43     scanf("%d",&t);
44     b[1]=2;b[2]=3;b[3]=4;b[4]=6;
45     while(t--){
46         ll n;
47         scanf("%I64d",&n);
48         if(n<=4) {
49             printf("%d\n",b[n]);continue;
50         }
51         mat.a[1][1]=0;mat.a[1][2]=0;mat.a[1][3]=1;
52         mat.a[2][1]=1;mat.a[2][2]=0;mat.a[2][3]=0;
53         mat.a[3][1]=0;mat.a[3][2]=1;mat.a[3][3]=1;
54         node A=hh(mat,n-4);
55   // cout<<t<<endl;
56         cout<<(b[2]*A.a[1][3]%mod+b[3]*A.a[2][3]%mod+b[4]*A.a[3][3]%mod+mod)%mod<<endl;
57
58     }
59     return 0;
60 }
时间: 2024-10-13 08:24:55

hdu 6030的相关文章

(hdu 6030) Happy Necklace 找规律+矩阵快速幂

题目链接 :http://acm.hdu.edu.cn/showproblem.php?pid=6030 Problem Description Little Q wants to buy a necklace for his girlfriend. Necklaces are single strings composed of multiple red and blue beads. Little Q desperately wants to impress his girlfriend,

HDU 6030 Happy Necklace

矩阵快速幂. #include <bits/stdc++.h> using namespace std; const long long mod=1e9+7; const long long inf=1e18; int T; long long n; struct Matrix { long long A[5][5]; int R, C; Matrix operator*(Matrix b); }; Matrix X, Y, Z; Matrix Matrix::operator*(Matrix

HDOJ 6030 矩阵快速幂

链接: http://acm.hdu.edu.cn/showproblem.php?pid=6030 题意: 给一个手链染色,每连续素数个数的珠子中红色不能比蓝的多,问有多少种情况 题解: 公式为f[i]=f[i-1]+f[i-3],类似菲波那切数列,使用矩阵快速幂即可 代码: 31 typedef vector<ll> vec; 32 typedef vector<vec> mat; 33 34 mat mul(mat &A, mat &B) { 35 mat C

hdu 4553 约会安排

约会安排 http://acm.hdu.edu.cn/showproblem.php?pid=4553 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Problem Description 寒假来了,又到了小明和女神们约会的季节. 小明虽为屌丝级码农,但非常活跃,女神们常常在小明网上的大段发言后热情回复“呵呵”,所以,小明的最爱就是和女神们约会.与此同时,也有很多基友找他开黑

HDU 6203 ping ping ping [LCA,贪心,DFS序,BIT(树状数组)]

题目链接:[http://acm.hdu.edu.cn/showproblem.php?pid=6203] 题意 :给出一棵树,如果(a,b)路径上有坏点,那么(a,b)之间不联通,给出一些不联通的点对,然后判断最少有多少个坏点. 题解 :求每个点对的LCA,然后根据LCA的深度排序.从LCA最深的点对开始,如果a或者b点已经有点被标记了,那么continue,否者标记(a,b)LCA的子树每个顶点加1. #include<Bits/stdc++.h> using namespace std;

HDU 5542 The Battle of Chibi dp+树状数组

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5542 题意:给你n个数,求其中上升子序列长度为m的个数 可以考虑用dp[i][j]表示以a[i]结尾的长度为j的上升子序列有多少 裸的dp是o(n2m) 所以需要优化 我们可以发现dp的第3维是找比它小的数,那么就可以用树状数组来找 这样就可以降低复杂度 #include<iostream> #include<cstdio> #include<cstring> #include

hdu 1207 汉诺塔II (DP+递推)

汉诺塔II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 4529    Accepted Submission(s): 2231 Problem Description 经典的汉诺塔问题经常作为一个递归的经典例题存在.可能有人并不知道汉诺塔问题的典故.汉诺塔来源于印度传说的一个故事,上帝创造世界时作了三根金刚石柱子,在一根柱子上从下往

[hdu 2102]bfs+注意INF

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2102 感觉这个题非常水,结果一直WA,最后发现居然是0x3f3f3f3f不够大导致的--把INF改成INF+INF就过了. #include<bits/stdc++.h> using namespace std; bool vis[2][15][15]; char s[2][15][15]; const int INF=0x3f3f3f3f; const int fx[]={0,0,1,-1};

HDU 3555 Bomb (数位DP)

数位dp,主要用来解决统计满足某类特殊关系或有某些特点的区间内的数的个数,它是按位来进行计数统计的,可以保存子状态,速度较快.数位dp做多了后,套路基本上都差不多,关键把要保存的状态给抽象出来,保存下来. 简介: 顾名思义,所谓的数位DP就是按照数字的个,十,百,千--位数进行的DP.数位DP的题目有着非常明显的性质: 询问[l,r]的区间内,有多少的数字满足某个性质 做法根据前缀和的思想,求出[0,l-1]和[0,r]中满足性质的数的个数,然后相减即可. 算法核心: 关于数位DP,貌似写法还是