zoukankan      html  css  js  c++  java
  • Comet OJ

    传送门

    (A)

    咕咕

    typedef long long ll;
    int a1,a2,n,d;ll res;
    int main(){
    	scanf("%d%d%d",&a1,&a2,&n);
    	d=a2-a1;
    	res=1ll*(a1+a1+1ll*(n-1)*d)*n>>1;
    	printf("%lld
    ",res);
    	return 0;
    }
    

    (B)

    不难发现答案要么是(1)要么是(2)

    当且仅当(k+1)是个质数且范围内为(k+1)的倍数的数只有一个时,答案为(1)否则为(2)

    据说(n=2)要特殊考虑,我是直接把(nleq 100)的情况用暴力跑了

    //quming
    #include<bits/stdc++.h>
    #define R register
    #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
    #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
    #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
    template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
    template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
    using namespace std;
    typedef long long ll;
    ll n,k;
    inline bool ck(R ll x){fp(i,2,sqrt(x))if(x%i==0)return false;return true;}
    int vis[105];
    void solve(){
    	R int p=1;
    	vis[k+1]=1;
    	fp(res,1,2333){
    		fp(i,2,n+1)if(vis[i]==res)
    			fp(j,2,n+1)if(!vis[j])
    				if(__gcd(i,j)==1)vis[j]=res+1,++p;
    		if(p==n)return printf("%d
    ",res),void();
    	}
    }
    int main(){
    	scanf("%lld%lld",&n,&k);
    	if(n<=100)return solve(),0;
    	puts(ck(k+1)&&(k+1)*2>n+1?"1":"2");
    	return 0;
    }
    

    (C)

    二分+点分

    二分最远的距离,同时强制点分中心必选,且以点分中心为根

    那么一个点会被选,当且仅当它的子树中有点被选,或者它的子树中离他最远的点到他的距离(=mid)(即二分出的最远距离),如果选的点数小于等于(k)说明合法

    因为点分的时候会删点,所以记得处理来自删点后的子树内的最远距离

    ps:据说这题直接倍增就可以过了

    //quming
    #include<bits/stdc++.h>
    #define R register
    #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
    #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
    #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
    template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
    template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
    using namespace std;
    const int N=5e5+5;
    struct eg{int v,nx;}e[N<<1];int head[N],tot;
    inline void add(R int u,R int v){e[++tot]={v,head[u]},head[u]=tot;}
    int sz[N],son[N],vis[N],ok[N],dis[N],las[N],rt,size;
    int l,r,mid,ans,n,k,sum;bool fl;
    inline int max(R int x,R int y){return x>y?x:y;}
    void findrt(int u,int fa){
    	sz[u]=1,son[u]=0;
    	go(u)if(!vis[v]&&v!=fa)findrt(v,u),sz[u]+=sz[v],cmax(son[u],sz[v]);
    	cmax(son[u],size-sz[u]);
    	if(son[u]<son[rt])rt=u;
    }
    void did(int u,int fa){
    	ok[u]=0,dis[u]=las[u];
    	go(u)if(!vis[v]&&v!=fa)did(v,u),cmax(dis[u],dis[v]+1),ok[u]|=ok[v];
    	ok[u]|=(dis[u]>=mid),sum+=ok[u];
    }
    void solve(int u){
    	vis[u]=1,sum=0;
    	did(u,0);
    	if(!ok[u])ok[u]=1,++sum;
    	if(sum<=k)return fl=1,void();
    	R int t1=0,t2=0,to=0;
    	go(u)if(!vis[v]){
    		if(dis[v]+1>=t2)t1=t2,t2=dis[v]+1,to=v;
    		else cmax(t1,dis[v]+1);
    	}
    	if(las[u]>=t2)t1=t2,t2=las[u],to=0;
    	else cmax(t1,las[u]);
    	R int ss=size;
    	go(u)if(!vis[v]){
    		las[v]=v==to?t1+1:t2+1;
    		if(las[v]>mid)continue;
    		rt=0,size=sz[v]>sz[u]?size-sz[u]:sz[v],findrt(v,0),solve(rt);
    		if(fl)return;
    	}
    }
    int ck(){
    	memset(las,0,(n+1)<<2);
    	memset(vis,0,(n+1)<<2);
    	fl=0,son[0]=n+1;
    	size=n,rt=0,findrt(1,0),solve(rt);
    	return fl;
    }
    int main(){
    	scanf("%d%d",&n,&k);
    	for(R int i=1,u,v;i<n;++i)scanf("%d%d",&u,&v),add(u,v),add(v,u);
    	int l=1,r=n;
    	while(l<=r){
    		mid=(l+r)>>1;
    		ck()?(ans=mid,r=mid-1):l=mid+1;
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    

    (D)

    考虑跳儿子的过程,如果是跳到一个轻儿子,那么子树大小减半,所以跳轻儿子的总次数不会超过(O(log n))次,所以我们只需要考虑优化跳重儿子的过程即可

    对于每一个点,我们记录它的重儿子在它的儿子中标号是多少,那么跳重儿子的话只要计算它的重链和(a_i)(LCP)即可,可以用二分+(Hash)求出

    复杂度(O(nlog^2 n))

    //quming
    #include<bits/stdc++.h>
    #define R register
    #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
    #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
    #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
    template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
    template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
    using namespace std;
    char buf[1<<21],*p1=buf,*p2=buf;
    inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
    int read(){
        R int res,f=1;R char ch;
        while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
        for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
        return res*f;
    }
    char sr[1<<21],z[20];int C=-1,Z=0;
    inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
    void print(R int x){
        if(C>1<<20)Ot();if(x<0)sr[++C]='-',x=-x;
        while(z[++Z]=x%10+48,x/=10);
        while(sr[++C]=z[Z],--Z);sr[++C]='
    ';
    }
    const int N=5e5+5;
    typedef unsigned long long ll;
    vector<int>to[N];ll bas[N];
    int n,q,m;
    struct Bit{
    	ll c[N];
    	inline void upd(R int x,R ll y){y*=bas[x];for(;x<=N-5;x+=x&-x)c[x]+=y;}
    	inline ll query(R int x){R ll res=0;for(;x;x-=x&-x)res+=c[x];return res;}
    	inline ll query(R int l,R int r){return (query(r)-query(l-1))*bas[N-5-l];}
    }T,G;
    int sz[N],son[N],id[N],ed[N],dfn[N],rk[N],fa[N],a[N],deg[N],tim,rt;
    void dfs1(int u){
    	sz[u]=1,sort(to[u].begin(),to[u].end());
    	R int c=0;
    	for(auto v:to[u]){
    		++c,dfs1(v),sz[u]+=sz[v];
    		if(sz[v]>sz[son[u]])son[u]=v,id[u]=c;
    	}
    }
    void dfs2(int u){
    	dfn[u]=++tim,rk[tim]=u,ed[u]=u;
    	if(!son[u])return T.upd(tim,-23333),void();
    	dfs2(son[u]),ed[u]=ed[son[u]],T.upd(dfn[u],id[u]);
    	for(auto v:to[u])if(v!=son[u])dfs2(v);
    }
    inline int min(R int x,R int y){return x<y?x:y;}
    int LCP(R int li,R int ri,R int l,R int r){
    	int lp=1,rp=min(r-l+1,ri-li+1),ans=0,mid;
    	while(lp<=rp){
    		mid=(lp+rp)>>1;
    		T.query(li,li+mid-1)==G.query(l,l+mid-1)?(ans=mid,lp=mid+1):rp=mid-1;
    	}
    	return ans;
    }
    int solve(R int u,R int l,R int r){
    	R int li=dfn[u],ri=dfn[ed[u]];
    	while(233){
    		R int len=LCP(li,ri,l,r);
    		li+=len,l+=len;
    		u=rk[li];
    		if(l>r||deg[u]<a[l])return u;
    		u=to[u][a[l]-1],li=dfn[u],ri=dfn[ed[u]],++l;
    		if(l>r)return u;
    	}
    }
    int main(){
    //	freopen("testdata.in","r",stdin);
    	n=read(),m=read(),q=read();
    	bas[0]=1;fp(i,1,N-5)bas[i]=bas[i-1]*19260817;
    	fp(i,1,n){
    		fa[i]=read();
    		if(fa[i])to[fa[i]].push_back(i),++deg[fa[i]];else rt=i;
    	}
    	dfs1(rt),dfs2(rt);
    	fp(i,1,m)a[i]=read(),G.upd(i,a[i]);
    	for(R int op,x,y,z;q;--q){
    		op=read(),x=read(),y=read();
    		if(op==2)G.upd(x,y-a[x]),a[x]=y;
    		else z=read(),print(solve(x,y,z));
    	}
    	return Ot(),0;
    }
    

    (E)

    用原根预处理之后(O(1))计算(i^i),同时直接暴力合并路径计算答案即可,具体细节看代码

    然后是关于复杂度的问题,若(u)为其中一个点,且(u)到某个叶子的路径上的点分别为(u,p_1,p_2,p_3,...,p_x),那么路径((u,u),(u,p_1),(u,p_2),...,(u,p_x))中,不同的(&)值只有(O(log a_i))种,所以假设是一条链,且以其中一个叶子为根,那么每一次把子树里的所有形如((v,i))的路径变成((u,i))的复杂度是(O(log a_i)),那么记(d)为叶子个数,在不合并路径的情况下复杂度为(O(ndlog a_i))

    对于路径的合并,两个叶子只会在它们的(LCA)处被合并一次,所以这部分复杂度为(O(d^2log^2 a_i)),然后又因为路径总数是(O(n^2)),且根据不等式(min(a,b)leq sqrt{ab}),所以(min(d^2log^2 a_i,n^2)leq O(ndlog a_i))

    综上复杂度复杂度为(O(ndlog a_i))

    //quming
    #include<bits/stdc++.h>
    #define R register
    #define pb push_back
    #define fi first
    #define se second
    #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
    #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
    #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
    template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
    template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
    using namespace std;
    const int P=786433,g=10;
    inline void upd(R int &x,R int y){(x+=y)>=P?x-=P:0;}
    inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;}
    inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
    inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
    int ksm(R int x,R int y){
    	R int res=1;
    	for(;y;y>>=1,x=mul(x,x))(y&1)?res=mul(res,x):0;
    	return res;
    }
    const int N=2e5+5;
    struct eg{int v,nx;}e[N<<1];int head[N],tot;
    inline void Add(R int u,R int v){e[++tot]={v,head[u]},head[u]=tot;}
    int ind[P],fpow[P];
    inline void init(){
    	fpow[0]=1;
    	for(R int x=g,i=1;x!=1;x=mul(x,g),++i)ind[x]=i,fpow[i]=x;
    }
    inline int calc(R int x,R int y){
    	if(x%=P,!x)return 0;
    	return fpow[1ll*ind[x]*y%(P-1)];
    }
    typedef pair<int,int> pi;
    int a[N],n,res;
    vector<pi> dfs(int u,int fa){
    	vector<pi> now(1,pi(a[u],1));
    	go(u)if(v!=fa){
    		vector<pi> to=dfs(v,u),tt;
    		for(auto &x:to)x.fi&=a[u];
    		pi p(0,0);
    		for(auto x:to)if(p.fi!=x.fi){
    			if(p.fi)tt.pb(p);
    			p=x;
    		}else p.se+=x.se;
    		if(p.fi)tt.pb(p);
    		for(const auto &x:now)for(const auto &y:tt)
    			upd(res,1ll*calc(x.fi&y.fi,x.fi&y.fi)*x.se*y.se%P);
    		now.insert(now.end(),tt.begin(),tt.end());
    	}
    	return now;
    }
    int main(){
    //	freopen("testdata.in","r",stdin);
    	scanf("%d",&n),init();
    	fp(i,1,n)scanf("%d",&a[i]),upd(res,calc(a[i],a[i]));
    	for(R int i=1,u,v;i<n;++i)scanf("%d%d",&u,&v),Add(u,v),Add(v,u);
    	dfs(1,0);
    	printf("%d
    ",res);
    	return 0;
    }
    

    (F)

    先考虑一个暴力,把(S)中每一个数的倍数都存在一个(bitset)里,记为(A),那么答案就是(A&(A>>1)&(A>>2))

    然而这样显然会(T),那么我们考虑设阈值,对于(x)大于阈值的部分,我们还是直接枚举倍数并记到(A)里,否则我们找出(x)的倍数的循环节的情况,然后在循环节上对(A)处理就行了

    顺便记得找循环节的时候千万别取模……(\%)的常数非常大甚至会(T)……

    //quming
    #include<bits/stdc++.h>
    #define R register
    #define pc(x) __builtin_popcountll(x)
    #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
    #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
    #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
    template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
    template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
    using namespace std;
    typedef unsigned long long ll;
    const int N=(1000000000>>6)+233;
    struct Bit{
    	ll p[N];
    	inline void ins(R int x){p[x>>6]|=(1ull<<(x&63));}
    }A;
    ll b[64*64+5];int n,S,mx,res;
    int main(){
    //	freopen("testdata.in","r",stdin);
    	scanf("%d%d",&n,&S),mx=(n>>6);
    	for(R int x;S;--S){
    		scanf("%d",&x);
    		if(x==1)return printf("%d
    ",n-2),0;
    		if(x<=64){
    			fp(i,0,x-1)b[i]=0;
    			for(R int i=0;i<(x<<6);i+=x)b[i>>6]|=(1ull<<(i&63));
    			for(R int i=0,j=0;i<=mx;++i){
    				A.p[i]|=b[j];
    				if(++j==x)j=0;
    			}
    		}else for(R int i=x;i<=n;i+=x)A.ins(i);
    	}
    	A.p[(n+1)>>6]&=(1ull<<((n+1)&63))-1;
    	fp(i,0,mx)res+=pc(A.p[i]&(A.p[i]>>1)&(A.p[i]>>2));
    	fp(i,1,mx){
    		R ll tmp=(A.p[i-1]>>62)|((A.p[i]&3)<<2);
    		res+=pc(tmp&(tmp>>1)&(tmp>>2));
    	}
    	printf("%d
    ",res);
    	return 0;
    }
    
  • 相关阅读:
    hdu 5071
    HDU4945 2048(dp)
    ZOJ3229 Shoot the Bullet(有源汇的上下界最大流)
    HDU Destroy Transportation system(有上下界的可行流)
    Treap模板
    HDU4916 Count on the path(树dp??)
    HDU2829 Lawrence(斜率优化dp)
    HDU3507 Print Article(斜率优化dp)
    POJ3164 Command Network(最小树形图)
    Codeforces 452E Three Strings(后缀自动机)
  • 原文地址:https://www.cnblogs.com/yuanquming/p/11421087.html
Copyright © 2011-2022 走看看