• 【XSY3947】完美串(思维/结论)


    题面

    完美串

    题解

    考虑一个完美串 (s) 应该满足什么性质。

    (s)(0)(1) 数量相同,那么显然是 (01) 交错的。

    否则不妨设 (1)(0) 多,那么循环意义下一定有连续的 (11),不然 (1) 不可能比 (0) 多。

    又由于有连续的 (11),那么就不能有连续的 (00),不然这个串就不是完美串。

    考虑一个 (1)(0) 多的完美串 (s),那么在循环意义下,(s) 可以被分割成若干段 (1),而且每段 (1) 之间恰好隔着一个 (0)

    (s) 的每段 (1) 中删去一个 (1) 得到一个新的字符串 (t),容易证明 (s) 是完美串当且仅当 (t) 是完美串。

    (0)(1) 多的情况同理。

    那么假设 (s) 中有 (x)(0)(y)(1)。这个过程其实相当于 ((x,y) o(x-y,y))((x,y) o (x,y-x)),也就是辗转相减的过程,而辗转相减可以优化成辗转相除。

    如果我们枚举一开始长度为 (n) 的完美串 (s) 中有 (i)(0)(n-i)(1) 的话,其实我们是可以模拟这个辗转相除的过程的。也就是说,我们可以从最后的串倒推回来 (s) 长什么样。

    那么我们一个一个把倒推回来的串 (s) 和题目给的串比较,看是否匹配就行了。

    bitset优化匹配可以做到 (O(dfrac{n^3}{w})) 的时间复杂度。

    代码如下:

    #include<bits/stdc++.h>
    
    #define un unsigned
    #define N 1050
    
    using namespace std;
    
    namespace modular
    {
    	const int mod=1000000007;
    	inline int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
    	inline int dec(int x,int y){return x-y<0?x-y+mod:x-y;}
    	inline int mul(int x,int y){return 1ll*x*y%mod;}
    }using namespace modular;
    
    inline int read()
    {
    	int x=0,f=1;
    	char ch=getchar();
    	while(ch<'0'||ch>'9')
    	{
    		if(ch=='-') f=-1;
    		ch=getchar();
    	}
    	while(ch>='0'&&ch<='9')
    	{
    		x=(x<<1)+(x<<3)+(ch^'0');
    		ch=getchar();
    	}
    	return x*f;
    }
    
    const un int base=1145141;
    
    int n,ans;
    int a[N],b[N];
    char s[N];
    
    bitset<N>now,ss,vis;
    
    int work(int x,int y,bool opt)
    {
    	if(!y)
    	{
    		for(int i=1;i<=x;i++) a[i]=opt;
    		return x;
    	}
    	int t=x/y;
    	int d=work(y,x-y*t,opt^1);
    	int nn=y+x-y*t;
    	int cnt=0;
    	for(int i=1;i<=nn;i++)
    	{
    		if(a[i]!=opt)
    			for(int j=1;j<=t;j++)
    				b[++cnt]=opt;
    		b[++cnt]=a[i];
    	}
    	for(int i=1;i<=x+y;i++) a[i]=b[i];
    	return d;
    }
    
    void solve(int d)
    {
    	now.reset();
    	for(int i=1;i<=n;i++)
    		if(a[i]) now.set(i);
    	if((now&vis)==ss) ans++;
    	for(int i=1;i<d;i++)
    	{
    		bool t=now[1];
    		now[1]=0;
    		now>>=1;
    		if(t) now.set(n);
    		if((now&vis)==ss) ans++;
    	}
    }
    
    int main()
    {
    	scanf("%d%s",&n,s+1);
    	for(int i=1;i<=n;i++)
    	{
    		if(s[i]!='?')
    		{
    			ss.set(i,s[i]-'0');
    			vis.set(i,1);
    		}
    	}
    	for(int i=0;i<=n;i++)
    	{
    		int d;
    		if(i<n-i) d=work(n-i,i,1);
    		else d=work(i,n-i,0);
    		solve(n/d);
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    /*
    4
    ?01?
    */
    /*
    10
    ??????????
    */
    
  • 相关阅读:
    tomcat7的catalina.sh配置说明
    nginx防攻击的简单配置
    linux系统自签发免费ssl证书,为nginx生成自签名ssl证书
    mysql ERROR 1045 (28000): Access denied for user 'root'@'localhost'
    /var/log/secure 文件清空
    Linux日志文件
    记一次网站被挂马处理
    Uedit32对文本进行回车换行
    安装mysql血泪史。
    mysql-8.0.19安装教程(Windows)
  • 原文地址:https://www.cnblogs.com/ez-lcw/p/14508515.html
Copyright © 2020-2023  润新知