清北刷题冲刺 10-30 p.m
Posted Soda
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了清北刷题冲刺 10-30 p.m相关的知识,希望对你有一定的参考价值。
少女
#include<iostream> #include<cstdio> #include<queue> #include<cstdlib> #define maxn 200010 #define mod 1000000007 using namespace std; int n,m,head[maxn],num,c[maxn],du[maxn]; int ans=1; bool vis[maxn]; struct node{ int to,pre,v; }e[maxn*2]; void Insert(int from,int to,int id,int v){ e[id].to=to; e[id].v=v; e[id].pre=head[from]; head[from]=id; } int Pow(int a,int b){ int res=1; while(b){ if(b&1)res=1LL*res*a%mod; a=1LL*a*a%mod; b>>=1; } return res; } void bfs(int s){ int count=0; queue<int>q; q.push(s);vis[s]=1; int cnt=0;//记录联通块中有多少边 while(!q.empty()){ int now=q.front();q.pop(); count+=c[now]; while(count>=mod)count-=mod; for(int i=head[now];i;i=e[i].pre){ if(e[i].v){ e[i].v=0; int nxt; if(i>m)nxt=i-m; if(i<=m)nxt=i+m; e[nxt].v=0; cnt+=1; if(!vis[e[i].to]){ vis[e[i].to]=1; q.push(e[i].to); } } } } int w=Pow(2,cnt)-count; if(w<=0){ puts("0");exit(0); } ans=1LL*ans*w%mod; while(ans>=mod)ans-=mod; } int main(){ freopen("girl.in","r",stdin);freopen("girl.out","w",stdout); // freopen("Cola.txt","r",stdin); scanf("%d%d",&n,&m); int x,y; for(int i=1;i<=m;i++){ scanf("%d%d",&x,&y); if(x==y)y+=n,n++; Insert(x,y,i,1);Insert(y,x,i+m,1); du[x]++;du[y]++; } for(int i=1;i<=n;i++){ c[i]=Pow(2,du[i])-1-du[i]; while(c[i]<0)c[i]+=mod; } for(int i=1;i<=n;i++){ if(!vis[i]){ bfs(i); } } printf("%d",ans); return 0; }
/* 对于图上每个联通块: 有>=2个环就无解; 有一个环就有2个解(顺时针和逆时针); 没有环,就是一棵树,n个点,n-1条边,所以有一个点没有边匹配,这个点有n种情况,所以有n个解 */ #include<iostream> #include<cstdio> #define maxn 100010 #define mod 1000000007 using namespace std; int n,m,x,y,fa[maxn],r[maxn],sz[maxn]; bool vis[maxn]; int find(int x){ if(x==fa[x])return x; else return fa[x]=find(fa[x]); } int main(){ freopen("girl.in","r",stdin);freopen("girl.out","w",stdout); // freopen("Cola.txt","r",stdin); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)fa[i]=i,sz[i]=1; for(int i=1;i<=m;i++){ scanf("%d%d",&x,&y); int f1=find(x),f2=find(y); if(f1==f2){ if(r[f1]){ puts("0"); return 0; } else r[f1]=1; } else { fa[f2]=f1; r[f1]|=r[f2]; sz[f1]+=sz[f2]; sz[f2]=0; } } long long ans=1; for(int i=1;i<=n;i++){ int father=find(i); if(!vis[father]){ vis[father]=1; if(r[father])ans=2LL*ans%mod; else ans=1LL*sz[father]*ans%mod; } } cout<<ans; return 0; }
终末
#include<iostream> #include<cstdio> using namespace std; long long n,bin[1000],ans,a[1000]; int k,cnt=-1; long long Pow(long long a,long long b){ long long res=1; while(b){ if(b&1)res=1LL*res*a; a=1LL*a*a; b>>=1; } return res; } int main(){ // freopen("Cola.txt","r",stdin); // freopen("endless.in","r",stdin);freopen("endless.out","w",stdout); cin>>n>>k; int t=0; while(1){ cnt=cnt+1; bin[cnt]=Pow(k,cnt); if(bin[cnt]>n)break; } for(long long i=0;i<=n;i++){ bool flag=0; long long now=i; for(int j=cnt;j>=0;j--){ a[j]=now/bin[j]; if(a[j]&&(j&1)){ flag=1;break; } now-=a[j]*bin[j]; } if(flag==0)ans++; } cout<<ans; }
/* 满足条件的数必须有一个性质,转成k进制后偶数位为0,奇数位为0~k-1 所以就是求<=n的数转化为k进制后偶数位全部为0的方案数 可以用数位dp求解 */ #include<iostream> #include<cstdio> #include<cmath> using namespace std; typedef long long LL; LL bit[67]; int a[67]; int main(){ freopen("endless.in","r",stdin);freopen("endless.out","w",stdout); long long n;int k;LL ans=0; scanf("%I64d%d",&n,&k); int len=0; while(n) a[++len]=n%k,n/=k; if(!(len&1)){ ans=pow(1LL*k,len/2); cout<<ans; } else{ for(int i=len;i>=1;i--) if(a[i]){ if(!(i&1)){ans+=pow(1LL*k,i/2);break;} ans+=1LL*a[i]*pow(1LL*k,i/2); if(i==1)ans++; } cout<<ans; } }
旅行
#include<iostream> #include<cstdio> #include<algorithm> #define maxn 100010 using namespace std; int n,num,head[maxn],v[maxn],k,le[maxn],cnt; long long w[maxn],ans,sum; int top[maxn],fa[maxn],son[maxn],sz[maxn],dep[maxn]; struct node{ int to,pre; }e[maxn*2]; void Insert(int from,int to){ e[++num].to=to; e[num].pre=head[from]; head[from]=num; } void dfs1(int now,int father){ dep[now]=dep[father]+1; fa[now]=father; sz[now]=1; w[now]=w[father]+v[now]; bool flag=0; for(int i=head[now];i;i=e[i].pre){ int to=e[i].to; if(to==father)continue; dfs1(to,now); sz[now]+=sz[to]; if(!son[now]||sz[to]>sz[son[now]])son[now]=to; flag=1; } if(!flag)le[++cnt]=now; } void dfs2(int now,int father){ top[now]=father; if(son[now])dfs2(son[now],father); for(int i=head[now];i;i=e[i].pre){ int to=e[i].to; if(to==fa[now]||to==son[now])continue; dfs2(to,to); } } int lca(int a,int b){ while(top[a]!=top[b]){ if(dep[top[a]]<dep[top[b]])swap(a,b); a=fa[top[a]]; } if(dep[a]>dep[b])swap(a,b); return a; } int q[maxn]; void count(){ long long now=0; for(int i=1;i<=k;i++)now+=w[q[i]]; for(int i=1;i<=k;i++) for(int j=i+1;j<=k;j++) now-=w[lca(q[i],q[j])]; ans=max(ans,now); } void dfs(int pos,int c){ if(c==k+1){ count(); return; } if(pos>cnt)return; if(cnt-pos<k-c)return; q[c]=le[pos]; dfs(pos+1,c+1); dfs(pos+1,c); } bool flag=1; bool cmp(int x,int y){return x>y;} int main(){ freopen("tour.in","r",stdin);freopen("tour.out","w",stdout); // freopen("Cola.txt","r",stdin); scanf("%d%d",&n,&k); if(k==0){ puts("0"); return 0; } int x,y; for(int i=1;i<=n;i++)scanf("%d",&v[i]),sum+=v[i]; for(int i=1;i<n;i++){ scanf("%d%d",&x,&y); Insert(x,y);Insert(y,x); if(x!=1&&y!=1)flag=0; } if(flag){ ans=v[1]; v[1]=0; sort(v+1,v+n+1,cmp); for(int i=1;i<=k;i++){ ans+=v[i]; } cout<<ans; return 0; } dfs1(1,0); dfs2(1,1); if(k>=cnt){ cout<<sum; return 0; } dfs(1,1); cout<<ans; return 0; }
/* 对树上的所有叶子节点到根的前缀和建一棵线段树,每次贪心选择前缀和最大的节点,并把路径上所有点为根节点的子树的叶子节点的前缀和减那个数,每次修改的都是一个连续的区间,所以可以用线段树的区间修改进行维护 */ #include<iostream> #include<algorithm> #include<cstdio> using namespace std; #define maxn 100010 int n,m,val[maxn],head[maxn],num; int opl,opr;long long opv; struct node{ int to,pre; }e[maxn*2]; int F[maxn],fa[maxn],id[maxn],cnt,L[maxn],R[maxn]; long long w[maxn],mx[maxn<<2],pos[maxn<<2],tag[maxn<<2]; void Insert(int from,int to){ e[++num].to=to; e[num].pre=head[from]; head[from]=num; } void init(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%d",&val[i]); int x,y; for(int i=1;i<n;i++){ scanf("%d%d",&x,&y); Insert(x,y);Insert(y,x); } } void dfs(int now,int father,long long sum){ L[now]=cnt+1; F[now]=now;bool leaf=1; fa[now]=father; for(int i=head[now];i;i=e[i].pre){ int to=e[i].to; if(to==father)continue; leaf=0; dfs(to,now,sum+val[to]); } if(leaf)w[++cnt]=sum,id[cnt]=now; R[now]=cnt; } void build(int l,int r,int k){ if(l==r){mx[k]=w[l];pos[k]=l;return;} int mid=(l+r)>>1; build(l,mid,k<<1); build(mid+1,r,k<<1|1); mx[k]=max(mx[k<<1],mx[k<<1|1]); pos[k]=(mx[k]==mx[k<<1]?pos[k<<1]:pos[k<<1|1]); } void down(int k){ mx[k<<1]-=tag[k]; mx[k<<1|1]-=tag[k]; tag[k<<1]+=tag[k]; tag[k<<1|1]+=tag[k]; tag[k]=0; } void change(int k,int l,int r){ if(opl<=l&&opr>=r){ mx[k]-=opv; tag[k]+=opv; return; } if(tag[k])down(k); int mid=(l+r)>>1; if(opl<=mid)change(k<<1,l,mid); if(opr>mid)change(k<<1|1,mid+1,r); mx[k]=max(mx[k<<1],mx[k<<1|1]); pos[k]=(mx[k]==mx[k<<1]?pos[k<<1]:pos[k<<1|1]); } int find(int x){ if(x==F[x])return x; return F[x]=find(F[x]); } void solve(){ int p;long long ans=0; while(m--){ p=id[pos[1]]; ans+=mx[1]; while(p){ opl=L[p];opr=R[p];opv=val[p]; change(1,1,cnt); F[p]=find(F[fa[p]]); p=F[p]; } } cout<<ans; } int main(){ freopen("tour.in","r",stdin);freopen("tour.out","w",stdout); // freopen("Cola.txt","r",stdin); init(); dfs(1,0,val[1]); build(1,cnt,1); solve(); }
预计得分100+40+30 实际得分0+40+30 T1错误比较大,是思路有误,根本原因在于自己造的样例没有包括全部的情况,以后引以为戒,不光要多造样例,更要尽可能想到更多的情况。T2T3写的时间不多,T2暴力分拿到了,T3wa了好几个,不知道为什么 今天下午时间把握不好,T1上浪费的时间太多而且思路偏离,T2T3草草写了暴力,难免出错,下不为例
以上是关于清北刷题冲刺 10-30 p.m的主要内容,如果未能解决你的问题,请参考以下文章