https://nanti.jisuanke.com/t/31721
题意 n个位置 有几个限制相邻的三个怎么怎么样,直接从3开始 矩阵快速幂进行递推就可以了
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const ll mod=1e9+7,maxn=9; 5 struct Matrix 6 { 7 ll m[maxn][maxn]; 8 Matrix() 9 { 10 memset(m,0,sizeof(m)); 11 } 12 void init() 13 { 14 for(int i=0; i<maxn; i++) 15 for(int j=0; j<maxn; j++) 16 m[i][j]=(i==j); 17 } 18 Matrix operator +(const Matrix &b)const 19 { 20 Matrix c; 21 for(int i=0; i<maxn; i++) 22 { 23 for(int j=0; j<maxn; j++) 24 { 25 c.m[i][j]=(m[i][j]+b.m[i][j])%mod; 26 } 27 } 28 return c; 29 } 30 Matrix operator *(const Matrix &b)const 31 { 32 Matrix c; 33 for(int i=0; i<maxn; i++) 34 { 35 for(int j=0; j<maxn; j++) 36 { 37 for(int k=0; k<maxn; k++) 38 { 39 c.m[i][j]=(c.m[i][j]+(m[i][k]*b.m[k][j])%mod)%mod; 40 } 41 } 42 } 43 return c; 44 } 45 Matrix operator^(const ll &t)const 46 { 47 Matrix ans,a=(*this); 48 ans.init(); 49 ll n=t; 50 while(n) 51 { 52 if(n&1) ans=ans*a; 53 a=a*a; 54 n>>=1; 55 } 56 return ans; 57 } 58 }; 59 int xishu[9][9]={ 60 0,0,0,1,0,0,1,0,0, 61 1,0,0,1,0,0,1,0,0, 62 1,0,0,1,0,0,0,0,0, 63 0,1,0,0,1,0,0,1,0, 64 0,1,0,0,0,0,0,1,0, 65 0,1,0,0,1,0,0,0,0, 66 0,0,1,0,0,0,0,0,1, 67 0,0,0,0,0,1,0,0,1, 68 0,0,1,0,0,1,0,0,0}; 69 int main() 70 { 71 int t; 72 ll n,m,a,b; 73 scanf("%d",&t); 74 while(t--) 75 { 76 scanf("%lld",&n); 77 if(n==1) 78 { 79 printf("3 "); 80 continue; 81 } 82 if(n==2) 83 { 84 printf("9 "); 85 continue; 86 } 87 Matrix temp,aa; 88 for(int i=0;i<maxn;i++) 89 { 90 for(int j=0;j<maxn;j++) 91 { 92 temp.m[i][j]=xishu[i][j]; 93 } 94 } 95 for(int i=0;i<maxn;i++) 96 aa.m[i][0]=1; 97 temp=temp^(n-2); 98 aa=temp*aa; 99 ll ans=0; 100 for(int i=0;i<maxn;i++) 101 ans=(ans+aa.m[i][0])%mod; 102 cout<<ans<<endl; 103 } 104 return 0; 105 }
https://nanti.jisuanke.com/t/31717
解析 傻逼题,数据范围应该是2e5,真是傻逼,被安排的明明白白。存个后缀自动机的板子。
#include<bits/stdc++.h> using namespace std; const int maxn = 2e5+5; typedef long long ll; char s[maxn]; int len,k,n,m; char temp[5]; struct SAM{ int last,cnt,nxt[maxn*2][26],fa[maxn*2],l[maxn*2],num[maxn*2]; ll ans; void init(){ last = cnt=1; memset(nxt[1],0,sizeof nxt[1]); fa[1]=l[1]=num[1]=0; ans=0; } int inline newnode(){ cnt++; memset(nxt[cnt],0,sizeof nxt[cnt]); fa[cnt]=l[cnt]=num[cnt]=0; return cnt; } void add(int c){ int p = last; int np = newnode(); last = np; l[np] =l[p]+1; while (p&&!nxt[p][c]){ nxt[p][c] = np; p = fa[p]; } if (!p){ fa[np] =1; }else{ int q = nxt[p][c]; if (l[q]==l[p]+1){ fa[np] =q; }else{ int nq = newnode(); memcpy(nxt[nq],nxt[q],sizeof nxt[q]); fa[nq] =fa[q]; num[nq] = num[q]; l[nq] = l[p]+1; fa[np] =fa[q] =nq; while (nxt[p][c]==q){ nxt[p][c]=nq; p = fa[p]; } } } int temp = last; while (temp){ if (num[temp]>=k){ break; } num[temp]++; if (num[temp]==k){ ans+=l[temp]-l[fa[temp]]; } temp = fa[temp]; } } }sam; int main(){ while (scanf("%s",s)!=EOF){ scanf("%d%d",&m,&k);k++; n=len = strlen(s); sam.init(); for (int i=0;i<len;i++){ sam.add(s[i]-'A'); } ll ans1=sam.ans; k=m; sam.init(); for (int i=0;i<len;i++){ sam.add(s[i]-'A'); } ll ans2=sam.ans; printf("%lld ",ans2-ans1); } return 0; }