zoukankan      html  css  js  c++  java
  • 【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
    ??????????
    */
    
  • 相关阅读:
    BUAA2020个人博客作业小结
    BUAA2020软工热身作业小结
    个人博客作业----总结
    个人阅读作业7
    超链接按钮点击变色,原来的链接恢复原色
    setInterval和setTimeout的区别以及setInterval越来越快问题的解决方法
    自定义网站404页面
    jQuery实现的上下滚动公告栏详细讲解
    K先生的博客
    Bootstrap4响应式布局之栅格系统
  • 原文地址:https://www.cnblogs.com/ez-lcw/p/14508515.html
Copyright © 2011-2022 走看看