hdu 6030 (矩阵快速幂)

来源:互联网 发布:金蝶erp软件二次开发 编辑:程序博客网 时间:2024/05/24 05:48

题意:给你一串珠子,要求任意素数区间段内红色大于蓝色,问有多少种方案。

赛后补题……
我们首先可以发现只要考虑2和3就可以了,因为其他任意区间都可以拆成2和3的组合,所以只要2和3满足就一定可以。
然后我们写一下就可以发现规律,如果新加一颗红色,那只要之前的满足就一定可以满足,如果新加一颗蓝色,只有红红蓝这种情况下才可以,所以就有递推式F(x)=F(x-1)+F(x-3)
2 3 4对应的情况我们可以先手动求出,
然后通过矩阵快速幂就可以求解。
因为ll贡献了一发WA……

#include <cstdio>#include <iostream>#include <algorithm>#include <cstring>#include <queue>#include <vector>using namespace std;typedef long long ll;typedef vector<ll> vec;typedef vector<vec> mat;const int mod=1e9+7;//计算A*Bmat mul(mat &A , mat &B){    mat C(A.size(),vec(B[0].size()));    for(int i=0;i<A.size();i++)        for(int k=0;k<B.size();k++)        for(int j=0;j<B[0].size();j++)            C[i][j]=(C[i][j]+A[i][k]*B[k][j])%mod;    return C;}//计算A^nmat pow(mat A,ll n){    mat B(A.size(),vec(A.size()));    for(int i=0;i<A.size();i++)        B[i][i]=1;    while(n>0)    {        if(n&1)B=mul(B,A);        A=mul(A,A);        n>>=1;    }    return B;}void print(mat A){    for(int i=0;i<A.size();i++)    {        for(int j=0;j<A[0].size();j++)            printf("%d ",A[i][j]);        printf("\n");    }}ll n;int ans[3]={3,4,6};void solve (){    mat A(3,vec(3));    A[0][0]=1;A[0][1]=0;A[0][2]=1;    A[1][0]=1;A[1][1]=0;A[1][2]=0;    A[2][0]=0;A[2][1]=1;A[2][2]=0;    A=pow(A,n-4);  //  print(A);    if(n>4)    printf("%d\n",(A[0][0]*6+A[0][1]*4+A[0][2]*3)%mod);    else {        printf("%d\n",ans[n-2]);    }}int main(){    int t;    cin>>t;    while(t--)    {        cin>>n;        solve();    }    return 0;}
0 0
原创粉丝点击