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
    ??????????
    */
    
  • 相关阅读:
    进程池线程池
    线程与其操作方法
    生产者消费者模型
    Java反射机制详解
    ajax跨域原理以及解决方案
    数据库连接池的选择 Druid
    新目标
    让webstorm支持avalon语法自动补全
    使用IDEA和gradle搭建Spring MVC和MyBatis开发环境
    使用IDEA自带的rest client参数传递乱码问题
  • 原文地址:https://www.cnblogs.com/ez-lcw/p/14508515.html
Copyright © 2011-2022 走看看