zoukankan      html  css  js  c++  java
  • CF1469E A Bit Similar

    CF1469E A Bit Similar

    因为这道题上了一百多分呢,刷新了div.2最高记录。如果我A题不挂两发直接上Master了/kk

    这是一种没有细节,只用敲863B的无脑方法,非常适合在打CF的时候使用。

    这题解法好多啊,而且怎么有2400啊,感觉偏高>_<


    看完题第一反应,一个串不可行,当且仅当它是原串某个长度为 (k) 的子串的反串。

    再看几眼灵光一闪直接就会了。把原串字符串哈希了,把每一个长度为 (k) 的串的反串丢进哈希表。然后维护一个二进制 (k) 位的大整数,初始为 (0),每次加 (1) ,模拟进位,动态维护这个新串的哈希值(这样显然字典序最小),直到这个串的哈希值不在原串出现,或者这个串已经是 (1111cdots111) 并且哈希值还是出现了,那就无解。

    进位直接均摊 $O( ext{次数}) $ ,显然最多修改 (n-k+1) 次。哈希为了不被卡用了 map ,虽然由于模数是自己设的不太能卡。所以复杂度大常数 (O(nlog n)) ,CF跑跑还是很轻松的,只用了 (800ms)

    真的非常无脑。只不过第一次写这个动态维护哈希,而且还是自己yy出来的,有点心虚。或许很多人也是第一次见到这玩意,还是详细讲一下吧:

    设当前串的哈希值为 (h)

    • 末尾加 (1) ,那么 (h+=1)

    • 如果第 (i) 位要进位,那么这一位减少 (2) ,下一位加 (1)(h+=base^{i+1}-2base^i)

    其实挺easy的。

    什么?可以只考虑最后 (20) 位?然后一群人因为没考虑前面的 (0) fst了?这种方法完全没事/cy,毫无细节,好写多了(

    你可能会问为啥这种东西你只写了863B。

    因为,我 有 板 子 /cy。字符串哈希什么的直接拉下来就能用。实际3.6k

    你可能会问CF用哈希不怕被卡吗?

    • Div.2 的rank1用的是1e7模数单哈希,我和同学一起叉了 (2h) 叉不掉。应该有很多人尝试叉他了,但是他活的好好的。
    • 你有本事把我这个hash叉掉,我请你吃饭。
    #include<bits/stdc++.h>
    using namespace std;
    #define fi first
    #define se second
    #define mkp(x,y) make_pair(x,y)
    #define pb(x) push_back(x)
    #define sz(v) (int)v.size()
    typedef long long LL;
    typedef double db;
    template<class T>bool ckmax(T&x,T y){return x<y?x=y,1:0;}
    template<class T>bool ckmin(T&x,T y){return x>y?x=y,1:0;}
    #define rep(i,x,y) for(int i=x,i##end=y;i<=i##end;++i)
    #define per(i,x,y) for(int i=x,i##end=y;i>=i##end;--i)
    inline int read(){
    	int x=0,f=1;char ch=getchar();
    	while(!isdigit(ch)){if(ch=='-')f=0;ch=getchar();}
    	while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    	return f?x:-x;
    }
    struct Rand{
    	unsigned long long sa,sb,sc;
    	static const int basic=(1<<30)-1;
    	Rand(){
    		srand(time(0));
    		sa=1ull*::rand()*::rand();
    		for(int i=1,up=::rand()%100;i<=up;++i)::rand();
    		srand(::rand()^clock());
    		sb=1ull*::rand()*::rand();
    		for(int i=1,up=::rand()%100;i<=up;++i)::rand();
    		srand(::rand()^clock());
    		sc=1ull*::rand()*::rand();
    	}
    	void init(){
    		srand(time(0));
    		sa=1ull*::rand()*::rand();
    		for(int i=1,up=::rand()%100;i<=up;++i)::rand();
    		srand(::rand()^clock());
    		sb=1ull*::rand()*::rand();
    		for(int i=1,up=::rand()%100;i<=up;++i)::rand();
    		srand(::rand()^clock());
    		sc=1ull*::rand()*::rand();
    	}
    	inline int rand(){
    		sa^=sa<<32,sa^=sa>>13,sa^=sa<<1;
    		unsigned long long t=sa;
    		sa=sb,sb=sc,sc^=t^sa;
    		return static_cast<int>(sc&basic)+1;
    	}
    	int rad(int l,int r){return rand()%(r-l+1)+l;}
    };
    
    template<int N>
    struct String_Hash{
    
    static const int O=N+5;
    LL H1[O],H2[O],pw1[O],pw2[O],mod1,mod2;
    int base1,base2;
    
    String_Hash(){
    	static const int base[8]={31,37,41,43,47,53,59,61};
    	static const LL mod[8]={100000000000031ll,100000000000367ll,100000000000169ll,100000000000261ll,
    	10000000000000069ll,10000000000000639ll,10000000000000753ll,10000000000000669ll};
    	static Rand maker;
    	base1=base[maker.rand()&7];
    	while((base2=base[maker.rand()&7])==base1);
    	mod1=mod[maker.rand()&7];
    	while((mod2=mod[maker.rand()&7])==mod1);
    	pw1[0]=1;for(int i=1;i<=N;++i)pw1[i]=pw1[i-1]*base1%mod1;
    	pw2[0]=1;for(int i=1;i<=N;++i)pw2[i]=pw2[i-1]*base2%mod2;
    }
    void insert(char*str,int n){
    	H1[0]=H2[0]=0;
    	for(int i=1;i<=n;++i)H1[i]=(H1[i-1]*base1+str[i]-'0'+1)%mod1;
    	for(int i=1;i<=n;++i)H2[i]=(H2[i-1]*base2+str[i]-'0'+1)%mod2;
    }
    LL mul(LL x,LL y,LL mod){
    	LL res=x*y-(LL)((long double)x/mod*y+0.5)*mod;
    	return res<0?res+mod:res;
    }
    pair<LL,LL>Hash_val(int l,int r){
    	LL v1=(H1[r]-mul(H1[l-1],pw1[r-l+1],mod1)+mod1)%mod1;
    	LL v2=(H2[r]-mul(H2[l-1],pw2[r-l+1],mod2)+mod2)%mod2;
    	return mkp(v1,v2);
    }
    
    };
    const int N=1000005;
    String_Hash<N>hs;
    int n,k,ans[N];
    char S[N],T[N];
    void Main(){
    	scanf("%d%d%s",&n,&k,S+1);
    	for(int i=1;i<=n;++i)T[i]='1'-S[i]+'0';
    	map<pair<LL,LL>,bool>mp;
    	hs.insert(T,n);
    	for(int i=1;i<=n-k+1;++i)mp[hs.Hash_val(i,i+k-1)]=1;
    	LL h1=0,h2=0;
    	for(int i=1;i<=k;++i)h1=(h1*hs.base1+1)%hs.mod1;
    	for(int i=1;i<=k;++i)h2=(h2*hs.base2+1)%hs.mod2;
    	for(int i=0;i<=k;++i)ans[i]=0;
    	for(int i=0;i<=n-k+1;++i){
    		if(!mp[mkp(h1,h2)]){
    			puts("YES");
    			for(int j=1;j<=k;++j)putchar(ans[j]+'0');
    			puts("");
    			return;
    		}
    		++ans[k],h1=(h1+1)%hs.mod1,h2=(h2+1)%hs.mod2;
    		int j=k;
    		while(ans[j]>1){
    			ans[j]=0,++ans[j-1];
    			h1=(h1+hs.pw1[k-j+1]-2ll*hs.pw1[k-j]%hs.mod1+hs.mod1)%hs.mod1;
    			h2=(h2+hs.pw2[k-j+1]-2ll*hs.pw2[k-j]%hs.mod2+hs.mod2)%hs.mod2;
    			--j;
    		}
    		if(j<=0)break;
    	}
    	puts("NO");
    }
    signed main(){for(int T=read();T;--T)Main();}
    
  • 相关阅读:
    Spark集群搭建步骤
    Hadoop集群搭建步骤
    Linux上传与下载(sz-rz)
    Spark文档
    Hadoop基本命令详解
    lzo压缩格式文件查看
    hadoop端口配置指南
    eclipse无法连接到makertplace
    Socket 服务端使用多线程实现多客户端通讯实例
    Jenkins和Sonar集成
  • 原文地址:https://www.cnblogs.com/zzctommy/p/14231884.html
Copyright © 2011-2022 走看看