• 51nod【1196】字符串的数量


    超级神题!
    有n种字符,若此种字符的编号( (1) ~ (n)),(i*2>n),则他后面可接任意字符。若不是,则他后面接的字符编号至少要是他的两倍。
    问长度为m的字符串的个数。
    这道题我只想出了 (O(n^2)) 的做法,于是叕只能求助题解。
    题解的做法和周六第二题有点像,但我并没有分析出最长链的长度小于 (log_{2}n) 这个性质。知道这个性质之后,就可以做了。
    (f[i]) 表示长度为 (i) 的合法字符串的个数。(g[i]) 表示长度为 (i) 的合法链的个数。
    转移就是

    [f[i]=sum_{j=1}^{maxlen}g[j]*f[i-j] ]

    (g[i]) 并不能直接转移,所以要设个辅助状态。
    (p[i][j]) 表示以 (j) 结尾,长度为 (i) 的链的个数,(g[i]) 就是 (p[i]) 里合法链的和。

    [p[i][j]=sum_{k=1}^{j/2}p[i-1][k] ]

    这个可以用前缀和优化,也可以将式子化简为从 (p[i][j-1]) 转移过来。

    [p[i][j]=p[i][j-1]+p[i-1][j/2]*(j mod 2==0) ]

    总复杂度 (O(m*log_{2}n))

    #include <bits/stdc++.h>
    using namespace std;
    
    #define db double
    #define ll long long
    #define RG register
    
    inline int gi()
    {
    	RG int ret; RG bool flag; RG char ch;
    	ret=0, flag=true, ch=getchar();
    	while (ch < '0' || ch > '9')
    		ch == '-' ? flag=false : 0, ch=getchar();
    	while (ch >= '0' && ch <= '9')
    		ret=(ret<<3)+(ret<<1)+ch-'0', ch=getchar();
    	return flag ? ret : -ret;
    }
    
    const db pi = acos(-1.0);
    const int N = 1e6+5, mod = 1e9+7;
    
    int f[N],g[N],p[22][N];
    
    int main()
    {
    	RG int n,m,len,i,j;
    	n=gi(), m=gi();
    	len=log2(n)+2;
    	p[1][1]=1, f[0]=1;
    	for (i=1; i<=len; ++i)
    		{
    			for (j=1; j<=n; ++j)
    				{
    					(p[i][j]+=p[i][j-1])%=mod;
    					if (j<<1 <= n)
    					(p[i+1][j<<1]+=p[i][j])%=mod;
    					else
    						(g[i]+=p[i][j])%=mod;
    				}
    		}
    	for (i=1; i<=m; ++i)
    		for (j=1; j<=len && j<=i; ++j)
    			(f[i]+=((ll)f[i-j]*g[j])%mod)%=mod;
    	printf("%d
    ",f[m]);
    	return 0;
    }
    
  • 相关阅读:
    在String中添加移动构造函数和移动赋值运算符
    自定义String类,并且实现在STL容器中添加自定义的类型
    allocator例子
    Messages的例子
    java unicode转中文
    Oracle Unicode转中文(解码)
    dom4j解析XML
    如何下载HLS视频到本地(m3u8)
    background-position
    XMPP协议实现即时通讯底层书写 (二)-- IOS XMPPFramework Demo+分析
  • 原文地址:https://www.cnblogs.com/y142857/p/7544962.html
Copyright © 2020-2023  润新知