标签:har opcode space ali printf out lan std tchar
https://vjudge.net/problem/TopCoder-15135
之前做过:本质不同的回文子序列个数
本题:位置不同即为不同。
如果还是设$f[l][r]$表示$l$,$r$结尾,就难受了。转移就已经是$O(n^2)$了
所以,$f[l][r]$表示,$[l,r]$的回文子序列个数
$f[l][r]=f[l+1][r]+f[l][r-1]-f[l+1][r-1]+(a[l]==a[r])*(f[l+1][r-1]+1)$
一个区间DP
但是要循环1e9次
但是其实,不管区间长度为多少,一共只有50种取值
所以,f[i][len]表示,扩展到长度为len的区间,[i,i+len-1]的子序列个数
显然i只有50个
然后矩乘转移即可。
100的size,因为还有len-2
#include<bits/stdc++.h> #define reg register int #define il inline #define fi first #define se second #define mk(a,b) make_pair(a,b) #define numb (ch^‘0‘) #define pb push_back #define solid const auto & #define enter cout<<endl #define pii pair<int,int> using namespace std; typedef long long ll; template<class T>il void rd(T &x){ char ch;x=0;bool fl=false;while(!isdigit(ch=getchar()))(ch==‘-‘)&&(fl=true); for(x=numb;isdigit(ch=getchar());x=x*10+numb);(fl==true)&&(x=-x);} template<class T>il void output(T x){if(x/10)output(x/10);putchar(x%10+‘0‘);} template<class T>il void ot(T x){if(x<0) putchar(‘-‘),x=-x;output(x);putchar(‘ ‘);} template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar(‘\n‘);} namespace Modulo{ const int mod=1e9+7; il int ad(int x,int y){return x+y>=mod?x+y-mod:x+y;} il int sub(int x,int y){return ad(x,mod-y);} il int mul(int x,int y){return (ll)x*y%mod;} il void inc(int &x,int y){x=ad(x,y);} il void inc2(int &x,int y){x=mul(x,y);} il int qm(int x,int y=mod-2){int ret=1;while(y){if(y&1) ret=mul(x,ret);x=mul(x,x);y>>=1;}return ret;} template<class ...Args>il int ad(const int a,const int b,const Args &...args) {return ad(ad(a,b),args...);} template<class ...Args>il int mul(const int a,const int b,const Args &...args) {return mul(mul(a,b),args...);} } using namespace Modulo; const int N=110; int n,m; struct tr{ int a[N][N]; tr(){memset(a,0,sizeof a);} void init(){ for(reg i=0;i<=m;++i){ a[i][i]=1; } } tr friend operator *(const tr &a,const tr &b){ tr c; for(reg k=0;k<=m;++k){ for(reg i=0;i<=m;++i){ for(reg j=0;j<=m;++j){ inc(c.a[i][j],mul(a.a[i][k],b.a[k][j])); } } } return c; } }S,A,B,C; tr qm(tr A,ll y){ tr ret; memset(ret.a,0,sizeof ret.a); ret.init(); while(y){ if(y&1) ret=ret*A; A=A*A; y>>=1; }return ret; } class LongPalindromes{ public: int count(int T,string s){ int n=s.length(); if(n==1) return qm(2,T); m=n*2; //0~n-1 //n~m-1 //a[0][m]=1 for(reg i=0;i<=n-1;++i){ A.a[i][i]=1; A.a[(i+1)%n][i]=1; A.a[i][i+n]=1; } A.a[m][m]=1; B.init(); for(reg len=1;len<=n;++len){ C=A; for(reg i=0;i<n;++i){ C.a[(i+1)%n+n][i]=sub((s[i]==s[(i+len-1)%n]),1); C.a[m][i]=(s[i]==s[(i+len-1)%n]); } B=B*C; } S.a[0][m]=1; S=S*qm(B,T); // printf("%d\n", return ad(S.a[0][0],1); } };
相同的保留一份即可。减少状态。利于矩乘。
TopCoder - 15135 LongPalindromes
标签:har opcode space ali printf out lan std tchar
原文地址:https://www.cnblogs.com/Miracevin/p/11041701.html