%%% dls
Poor God Water
题目描述
God Water likes to eat meat, fish and chocolate very much, but unfortunately, the doctor tells him that some sequence of eating will make them poisonous.
Every hour, God Water will eat one kind of food among meat, fish and chocolate. If there are 3 continuous hours when he eats only one kind of food, he will be unhappy. Besides, if there are 3 continuous hours when he eats all kinds of those, with chocolate at the middle hour, it will be dangerous. Moreover, if there are 3 continuous hours when he eats meat or fish at the middle hour, with chocolate at other two hours, it will also be dangerous.
Now, you are the doctor. Can you find out how many different kinds of diet that can make God Water happy and safe during N hours? Two kinds of diet are considered the same if they share the same kind of food at the same hour. The answer may be very large, so you only need to give out the answer module 1000000007.
输入
The fist line puts an integer T that shows the number of test cases. (T≤1000)
Each of the next T lines contains an integer N that shows the number of hours. (1≤N≤10^10)
输出
For each test case, output a single line containing the answer.
样例输入
复制样例数据
3
3
4
15
样例输出
20
46
435170
题意:
有n天,有三种食物:鱼,巧克力,肉,问你有多少种饮食方案
约束条件是:①:连续三天不能吃同一种食物;②:连续三小时中,中间是巧克力,两边是鱼和肉,也不行
③:连续三小时,中间是鱼或肉,两边是巧克力的话也不行
方法:
①:杜教的BM递推(原来大佬的世界都是自己发明代码吗。。瑟瑟发抖)
对于线性的递推式,如果取模是个质数的话,就可以套用这个模板了(orz)
②: 根据关系写出矩阵的状态转移来,然后有矩阵快速幂求解即可
先放杜教的BM模板下改编的这道题过得代码
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll _,n;
namespace linear_seq{
const int N=10010;
ll res[N],base[N],_c[N],_md[N];
vector<ll> Md;
void mul(ll *a,ll *b,int k)
{
rep(i,0,k+k) _c[i]=0;
rep(i,0,k) if (a[i]) rep(j,0,k) _c[i+j]=(_c[i+j]+a[i]*b[j])%mod;
for (int i=k+k-1;i>=k;i--) if (_c[i])
rep(j,0,SZ(Md)) _c[i-k+Md[j]]=(_c[i-k+Md[j]]-_c[i]*_md[Md[j]])%mod;
rep(i,0,k) a[i]=_c[i];
}
int solve(ll n,VI a,VI b)
{
ll ans=0,pnt=0;
int k=SZ(a);
assert(SZ(a)==SZ(b));
rep(i,0,k) _md[k-1-i]=-a[i];_md[k]=1;
Md.clear();
rep(i,0,k) if (_md[i]!=0) Md.push_back(i);
rep(i,0,k) res[i]=base[i]=0;
res[0]=1;
while ((1ll<<pnt)<=n) pnt++;
for (int p=pnt;p>=0;p--)
{
mul(res,res,k);
if ((n>>p)&1)
{
for (int i=k-1;i>=0;i--) res[i+1]=res[i];res[0]=0;
rep(j,0,SZ(Md)) res[Md[j]]=(res[Md[j]]-res[k]*_md[Md[j]])%mod;
}
}
rep(i,0,k) ans=(ans+res[i]*b[i])%mod;
if (ans<0) ans+=mod;
return ans;
}
VI BM(VI s) {
VI C(1,1),B(1,1);
int L=0,m=1,b=1;
rep(n,0,SZ(s)) {
ll d=0;
rep(i,0,L+1) d=(d+(ll)C[i]*s[n-i])%mod;
if (d==0) ++m;
else if (2*L<=n) {
VI T=C;
ll c=mod-d*powmod(b,mod-2)%mod;
while (SZ(C)<SZ(B)+m) C.pb(0);
rep(i,0,SZ(B)) C[i+m]=(C[i+m]+c*B[i])%mod;
L=n+1-L; B=T; b=d; m=1;
} else {
ll c=mod-d*powmod(b,mod-2)%mod;
while (SZ(C)<SZ(B)+m) C.pb(0);
rep(i,0,SZ(B)) C[i+m]=(C[i+m]+c*B[i])%mod;
++m;
}
}
return C;
}
int gao(VI a,ll n){
VI c=BM(a);
c.erase(c.begin());
rep(i,0,SZ(c)) c[i]=(mod-c[i])%mod;
return solve(n,c,VI(a.begin(),a.begin()+SZ(c)));
}
};
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int t;
cin>>t;
while(t--)
{
cin>>n;
int arr[17]={3,9,20,46,106,244,560,1286,2956,6794};
vector<int> v(arr,arr+10);
cout<<linear_seq::gao(v,n-1)%mod<<endl;
}
}
矩阵快速幂模板
#include<bits/stdc++.h>
typedef long long ll;
const int mod=1000000007;
const int N=9;
using namespace std;
struct matrix
{
ll m[N][N];
};
matrix mul(matrix a,matrix b)
{
matrix ans;
memset(ans.m,0,sizeof(ans.m));
for(int i=0; i<N; i++)
for(int j=0; j<N; j++)
for(int k=0; k<N; k++)
{
ans.m[i][j]+=a.m[i][k]*b.m[k][j];
ans.m[i][j]%=mod;
}
return ans;
}
matrix qpow(matrix a,ll b)
{
matrix ans,tmp=a;
for(int i=0; i<N; i++)
for(int j=0; j<N; j++)
ans.m[i][j]=i==j?1:0;
while(b)
{
if(b&1) ans=mul(ans,tmp);
b>>=1;
tmp=mul(tmp,tmp);
}
return ans;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin>>t;
while(t--)
{
ll n;
cin>>n;
if(n<=2)
{
if(n==1)
cout<<"3"<<endl;
else if(n==2)
cout<<"9"<<endl;
}
else{
matrix ret=
{
0,0,0, 1,0,0, 1,0,0,
1,0,0, 0,0,0, 1,0,0,
1,0,0, 1,0,0, 1,0,0,
0,1,0, 0,1,0, 0,0,0,
0,1,0, 0,0,0, 0,1,0,
0,0,0, 0,1,0, 0,1,0,
0,0,1, 0,0,1, 0,0,1,
0,0,1, 0,0,0, 0,0,1,
0,0,1, 0,0,1, 0,0,0
};
matrix ans;
ans=qpow(ret,n-2);
ll sum=0;
for(int i=0;i<N;i++)
for(int j=0;j<N;j++)
sum=(sum+ans.m[i][j])%mod;
cout<<sum<<endl;
}
}
return 0;
}