zoukankan      html  css  js  c++  java
  • HDU

    ( ext{Description})

    传送门

    ( ext{Solution})

    可以看看这道题的前置版本:( ext{POJ - 2778 DNA Sequence}),这样会容易理解一点。

    容易发现其实方案数就是所有长度小于等于 (m) 的方案数 (-) 长度小于等于 (m) 的不包含任何关键串的方案数。

    考虑第一项其实就是 (26^1+26^2+...+26^n)

    这个可以用等比数列求和或者用矩阵加速来递推。

    讲一下矩阵加速。令 (f_n=1+26^1+26^2+...+26^n)

    显然有:

    [f_n=f_{n-1} imes 26+1 ]

    最后求出 (f_n)(-1) 就是第一项。

    对于第二项,由于我们需要将矩阵的 ([1,m]) 的状态的第一行之和再相加,可以在矩阵后面添置一维。

    比如原矩阵为:

    [left[ egin{matrix} 1 & 2 \ 3 & 4 \ end{matrix} ight] ]

    我们将最后一列置为 (1),最后一行除了最后一列的那个置为 (0)

    [left[ egin{matrix} 1 & 2 & 1 \ 3 & 4 & 1 \ 0 & 0 & 1 end{matrix} ight] ]

    你会发现这样无论矩阵怎么乘最后一行是不变的,最后一列除了最后一行的那个数都是上一轮的同行的数相加,比如我们计算上面那个矩阵的平方时,((0,2)) 的答案就是 (1+2+1)。而且保证原矩阵范围未受影响。

    注意这样算出来的答案要减去初始赋值的 (1)

    ( ext{Code})

    #include <cstdio>
    
    #define rep(i,_l,_r) for(register signed i=(_l),_end=(_r);i<=_end;++i)
    #define fep(i,_l,_r) for(register signed i=(_l),_end=(_r);i>=_end;--i)
    #define erep(i,u) for(signed i=head[u],v=to[i];i;i=nxt[i],v=to[i])
    #define efep(i,u) for(signed i=Head[u],v=to[i];i;i=nxt[i],v=to[i])
    #define print(x,y) write(x),putchar(y)
    
    template <class T> inline T read(const T sample) {
        T x=0; int f=1; char s;
        while((s=getchar())>'9'||s<'0') if(s=='-') f=-1;
        while(s>='0'&&s<='9') x=(x<<1)+(x<<3)+(s^48),s=getchar();
        return x*f;
    }
    template <class T> inline void write(const T x) {
        if(x<0) return (void) (putchar('-'),write(-x));
        if(x>9) write(x/10);
        putchar(x%10^48);
    }
    template <class T> inline T Max(const T x,const T y) {if(x>y) return x; return y;}
    template <class T> inline T Min(const T x,const T y) {if(x<y) return x; return y;}
    template <class T> inline T fab(const T x) {return x>0?x:-x;}
    template <class T> inline T gcd(const T x,const T y) {return y?gcd(y,x%y):x;}
    template <class T> inline T lcm(const T x,const T y) {return x/gcd(x,y)*y;}
    template <class T> inline T Swap(T &x,T &y) {x^=y^=x^=y;}
    
    #include <queue>
    #include <cstring>
    using namespace std;
    typedef unsigned long long ll;
    
    queue <int> q;
    ll ans,sum;
    int n,m,t[35][30],f[35],tot;
    bool no[35];
    char s[10];
    struct Matrix {
    	ll a[35][35]; int n,m;
    	Matrix() {memset(a,0,sizeof a);}
    	Matrix operator * (Matrix t) {
    		Matrix r; r.n=n,r.m=m;
    		rep(i,0,r.n)
    			rep(j,0,r.m)
    				if(a[i][j])
    					rep(k,0,r.m)
    						r.a[i][k]=(r.a[i][k]+a[i][j]*t.a[j][k]);
    		return r;
    	}
    } per;
    
    Matrix qkpow(int y) {
    	Matrix r; r.n=r.m=per.n;
    	rep(i,0,r.n) r.a[i][i]=1;
    	while(y) {
    		if(y&1) r=r*per;
    		per=per*per; y>>=1;
    	}
    	return r;
    }
    
    void Insert() {
    	int p=0,len=strlen(s+1);
    	rep(i,1,len) {
    		int d=s[i]-'a';
    		if(!t[p][d]) t[p][d]=++tot;
    		p=t[p][d];
    	}
    	no[p]=1;
    }
    
    void GetFail() {
    	rep(i,0,25) if(t[0][i]) q.push(t[0][i]);
    	while(!q.empty()) {
    		int u=q.front(); q.pop();
    		rep(i,0,25)
    			if(t[u][i]) f[t[u][i]]=t[f[u]][i],q.push(t[u][i]),no[t[u][i]]|=no[f[t[u][i]]];
    			else t[u][i]=t[f[u]][i];
    	}
    } 
    
    void Ori() {
    	sum=ans=0; tot=0; per=Matrix();
    	memset(t,0,sizeof t);
    	memset(no,0,sizeof no);
    	memset(f,0,sizeof f);
    }
    
    void init() {
    	per=Matrix();
    	rep(i,0,tot)
    		if(!no[i])
    			rep(j,0,25)
    				if(!no[t[i][j]]) ++per.a[i][t[i][j]];
    	per.n=per.m=tot+1;
    	rep(i,0,per.m) per.a[i][per.m]=1;
    }
    
    int main() {
    	while(~scanf("%d %d",&n,&m)) {
    		Ori();
    		while(n--) scanf("%s",s+1),Insert();
    		GetFail(); init();
    		per=qkpow(m);
    		rep(i,0,per.m) ans+=per.a[0][i];
    		per=Matrix(); per.n=per.m=1;
    		per.a[0][0]=26,per.a[1][0]=per.a[1][1]=1;
    		per=qkpow(m);
    		rep(i,0,1) sum+=per.a[i][0];
    		print(sum-ans,'
    '); // sum 与 ans 都多计算了一个 1,所以直接相减就是答案
    	}
    	return 0;
    }
    

    ( ext{Bi Bi Time!})

    等比数列求和推出来答案柿子是:

    [frac{26^n imes 26-26}{25} ]

    然后我跑去求 (25)(2^{64}) 意义下的逆元,求出来这个东西:(15170602326218735249)

    但为什么乘出来不是 (1)?按理来说这两个玩意儿互质不是会有逆元吗?

  • 相关阅读:
    iOS如何隐藏状态栏,包括网络标志、时间标志、电池标志等
    xcrun: error: active developer path
    我们很少有机会看到一个人的所有面
    默妹(二)
    Bootstrap3的响应式缩略图幻灯轮播效果设计
    纯CSS3实现图片展示特效
    解决div设置浮动,高度消失
    解决css设置背景透明,文字不透明
    从零开始学习jQuery (六) jquery中的AJAX使用
    如何利用开源思想开发一个SEO友好型网
  • 原文地址:https://www.cnblogs.com/AWhiteWall/p/14124114.html
Copyright © 2011-2022 走看看