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
    ??????????
    */
    
  • 相关阅读:
    使用mongoose--写接口
    数据结构上机实验(2)
    时间复杂度十道练习题目
    Python网络爬虫实战入门
    区分矩阵的三大关系
    用python检查矩阵的计算
    ab矩阵(实对称矩阵)
    Python大数据应用
    数据结构上机实验(1)
    0038. Count and Say (E)
  • 原文地址:https://www.cnblogs.com/ez-lcw/p/14508515.html
Copyright © 2011-2022 走看看