zoukankan      html  css  js  c++  java
  • 「考试总结」20200724初音

    A.字符串识别

    Description

    link

    Solution

    这题问题出在了对于一个后缀自动机,这里如果在 (DAG) 上面进行操作,复杂度是 (O(n^2))

    所以我们换个思路做,还是考虑那些 (endpos) 集合大小为 (1) 的字符串

    看看贡献:

    [iin [i-len_{fa_i}+1,i] ans_i=min(ans_i,len_{fa_i}+1) ]

    [iin[i-len_i+1,i-len_{fa_i}] ans_i=min(ans_i,len_p-i+1) ]

    对于第一种情况,线段树统计答案

    对于第二种情况,观察到 (ans_i) 这一项总是加着一个 (i)

    那么先统一加上,然后最后面减掉,对位置减就好的

    另外,区间取 (min) 的线段树,需要好好记得怎么写……

    Code

    #include<bits/stdc++.h>
    using namespace std;
    namespace yspm{
    	inline int read()
    	{
    		int res=0,f=1; char k;
    		while(!isdigit(k=getchar())) if(k=='-') f=-1;
    		while(isdigit(k)) res=res*10+k-'0',k=getchar();
    		return res*f;
    	}
    	const int N=5e5+10,M=15e5+10;
    	int ans[N],le;
    	struct SGT{
    		int maxx[N<<2];
    		#define maxx(p) maxx[p]
    		inline void build(int p,int l,int r,int val)
    		{
    			if(l==r) return maxx(p)=le+l*val,void();
    			int mid=(l+r)>>1; build(p<<1,l,mid,val); build(p<<1|1,mid+1,r,val);
    			return maxx(p)=2e9+10,void();
    		}
    		inline void update(int p,int st,int ed,int l,int r,int val)
    		{
    			if(l<=st&&ed<=r) return maxx(p)=min(maxx(p),val),void();
    			int mid=(st+ed)>>1; 
    			if(l<=mid) update(p<<1,st,mid,l,r,val);
    			if(r>mid) update(p<<1|1,mid+1,ed,l,r,val); 
    			return ;
    		}		
    		inline void work(int p,int st,int ed,int val)
    		{
    			if(st==ed)
    			{
    				ans[st]=min(ans[st],maxx(p)-val*st);
    				return ;
    			} 
    			int mid=(st+ed)>>1;
    			maxx(p<<1)=min(maxx(p<<1),maxx(p));
    			maxx(p<<1|1)=min(maxx(p<<1|1),maxx(p));
    			work(p<<1,st,mid,val); work(p<<1|1,mid+1,ed,val);
    			return ;
    		}
    	}T1,T2;
    	struct edg{
    		int to,nxt;
    	}e[M<<1];
    	int head[M],cnt;
    	inline void add(int u,int v)
    	{
    		e[++cnt].to=v; e[cnt].nxt=head[u];
    		return head[u]=cnt,void();
    	}
    	int son[M][26],fa[M],len[M],tot=1,r[M],las=1,sz[M];
    	inline void copy(int x,int y)
    	{
    		for(int i=0;i<26;++i) son[x][i]=son[y][i];
    		return ;
    	} 
    	inline void extend(int x,int id)
    	{
    		int tmp=las,np=las=++tot; len[np]=len[tmp]+1; sz[np]=1; r[np]=id;
    		while(tmp&&!son[tmp][x]) son[tmp][x]=np,tmp=fa[tmp];
    		if(!tmp) return fa[np]=1,void();
    		int q=son[tmp][x];
    		if(len[q]==len[tmp]+1) return fa[np]=q,void();
    		int clone=++tot; len[clone]=len[tmp]+1;
    		fa[clone]=fa[q],fa[np]=fa[q]=clone; copy(clone,q); r[clone]=x;
    		while(tmp&&son[tmp][x]==q) son[tmp][x]=clone,tmp=fa[tmp];
     		return ;
    	} 
    	inline void dfs(int x)
    	{
    		for(int i=head[x];i;i=e[i].nxt)
    		{
    			int t=e[i].to; dfs(t); 
    			sz[x]+=sz[t];
    		}
    		if(sz[x]==1) 
    		{
    			T1.update(1,1,le,r[x]-len[fa[x]]+1,r[x],len[fa[x]]+1);
    			T2.update(1,1,le,r[x]-len[x]+1,r[x]-len[fa[x]],len[x]+1);
    		}
    		return ;
    	}	
    	char s[N];
    	signed main()
    	{
    		memset(ans,0x3f,sizeof(ans));
    		scanf("%s",s+1); le=strlen(s+1); 
    		T1.build(1,1,le,0); 
    		T2.build(1,1,le,1); 
    		for(int i=1;i<=le;++i) extend(s[i]-'a',i); 
    		for(int i=1;i<=tot;++i) add(fa[i],i); dfs(1);
    		T1.work(1,1,le,0); 
    		T2.work(1,1,le,1);
    		for(int i=1;i<=le;++i) printf("%d
    ",ans[i]);
    		return 0;
    	}
    }
    signed main(){return yspm::main();}
    
    

    B. CQOI2015 选数

    Descripion

    [sum_{a_1=L}^R sum_{a_2=L}^Rdotssum_{a_n=L}^R [gcd(a_1,a_2,a_3,dots,a_n)=k] (mod 10^9+7) ]

    所有参量满足 (le 10^9)

    Solution

    式子真难看,反手一推变成

    [sum_{i=1}^{lfloor frac R k floor} mu(i) (lfloor frac {lfloor frac R k floor} i floor-frac {lfloor frac L k floor} i floor)^n ]

    (考试的时候推错式子了……然后外加一些手残就爆零了)

    其实搞几个变量代替一下就没这么麻烦了……

    然后我们发现这种做法需要开不下的空间做 (mu)

    然后去学了一下杜教筛就做完了

    或者容斥大佬会这种做法

    Code

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    #define inf (int)1e18+10
    namespace yspm{
    	inline int read()
    	{
    		int res=0,f=1; char k;
    		while(!isdigit(k=getchar())) if(k=='-') f=-1;
    		while(isdigit(k)) res=res*10+k-'0',k=getchar();
    		return res*f;
    	}
    	const int mod=1e9+7;
    	inline int ksm(int x,int y)
    	{
    		int res=1; 
    		for(;y;y>>=1,x=x*x%mod) if(y&1) res=res*x%mod;
    		return res;
    	}
    	inline int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
    	const int N=7e6+10;
    	bool fl[N];
    	int pri[N],cnt,mu[N],n,l,h,k,ans,low,up;
    	inline void prework()
    	{
    		mu[1]=1;
    		for(int i=2;i<N;++i) 
    		{
    			if(!fl[i]) pri[++cnt]=i,mu[i]=mod-1;
    			for(int j=1;j<=cnt&&i*pri[j]<N;++j) 
    			{
    				fl[i*pri[j]]=1;
    				if(i%pri[j]==0){mu[i*pri[j]]=0; break;}
    				else mu[i*pri[j]]=-mu[i],mu[i*pri[j]]=(mu[i*pri[j]]+mod)%mod;
    			}
    		} 
    		for(int i=1;i<N;++i) mu[i]=add(mu[i],mu[i-1]);
    		return ;
    	}
    	map<int,int> mp;
    	inline void calc(int x,int &ans)
    	{
    		if(x<N) return ans=mu[x],void();
    		if(mp[x]) return ans=mp[x],void();
    		ans=1; 
    		for(int l=2,r,s=0;l<=x;l=r+1)
    		{
    			r=x/(x/l); s=0;
    			calc(x/l,s);
    			(s+=mod)%mod;
    			ans-=(r-l+1)*s%mod; 
    			ans=add(ans,mod);
    		} return mp[x]=ans,void();
    	}
    	inline int ask(int x)
    	{
    		int ans=0; calc(x,ans); return ans;
    	}
    	signed main()
    	{
    		n=read(); k=read(); l=read(); h=read();
    		low=(l-1)/k; up=h/k;
    		if(low>up) return puts("0"),0;
    		prework(); 
    		for(int i=1,j;i<=up;i=j+1)
    		{
    			j=min(low/i?low/(low/i):inf,up/(up/i));
    			ans=add(ans,(ask(j)-ask(i-1)+mod)%mod*ksm(up/i-low/i,n)%mod);
    		} cout<<ans<<endl;
    		return 0;
    	}
    }
    signed main(){return yspm::main();}
    

    C.树点涂色

    (sb) 的一个题目了,不到二十天之前刚刚做完,然后今天就忘记了

    不写了,直接贴link

    总结

    感觉上午状态很诡异,上手记错了一个结论,线段树写了一个多小时,还妄想自己能 (AK) 结果呢?

    (20)

    好好的 (lct) 不会打,反演的式子还推错

    我服了我自己,慢慢考试慢慢进步吧

  • 相关阅读:
    矩阵树定理(Kirchhoff || Laplace)初探——Part 1(无向图计数)
    AC自动机——看似KMP在跑,其实fail在跳
    逆序数模板
    牛客暑期五几何题
    priority_queue()大根堆和小根堆(二叉堆)
    STL中去重函数unique
    简单判断long long 以内的回文数
    素数判断和素数筛(简单方便)
    记忆化递归
    map详细的复习
  • 原文地址:https://www.cnblogs.com/yspm/p/13373158.html
Copyright © 2011-2022 走看看