CodeForces:749(div1)750(div2)
文章目錄
- 前言
- CF450A Jzzhu and Children
- Description\text{Description}Description
- Solution\text{Solution}Solution
- Code\text{Code}Code
- CF450B Jzzhu and Sequences
- Description\text{Description}Description
- Solution\text{Solution}Solution
- Code\text{Code}Code
- CF449A Jzzhu and Chocolate
- Description\text{Description}Description
- Solution\text{Solution}Solution
- Code\text{Code}Code
- CF449B Jzzhu and Cities
- Description\text{Description}Description
- Solution\text{Solution}Solution
- Solution\text{Solution}Solution
- CF449C Jzzhu and Apples
- Description\text{Description}Description
- Solution\text{Solution}Solution
- Code\text{Code}Code
- CF449D Jzzhu and Numbers
- Description\text{Description}Description
- Solution\text{Solution}Solution
- Code\text{Code}Code
- CF749E Inversions After Shuffle 題解
前言
750AB是水題.
749A小清新也比較水但有一點細節
749B經典的那種需要稍微想想但不難的圖論藍題
749C是裹著圖論的貪心題
749D的預處理是魔法操作之前沒有見過(據說還可以暴力FWT?)
749E大式子題我直接棄療
CF450A Jzzhu and Children
Description\text{Description}Description
nnn 個孩子排成隊,每個孩子有一個需求 aia_iai?.
每次給隊首的孩子 mmm 個糖果,如果還沒有滿足需求,該孩子就回到隊尾,否則就離開.
求最后一個離開的是誰.
Solution\text{Solution}Solution
水題,?ain?\lceil \dfrac{a_i}{n}\rceil?nai??? 求出每個孩子需要幾輪,然后取一個輪數最大即可.
同一輪數取編號最大.
Code\text{Code}Code
#include<bits/stdc++.h> using namespace std; #define ll long long //#define double long double #define debug(...) fprintf(stderr,__VA_ARGS__) const int N=1050; const double eps=1e-10; inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f; } int n,m; int a[105]; int main(){#ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout); #endifn=read();m=read();for(int i=1;i<=n;i++) a[i]=read();int mx=0,id=0;for(int i=1;i<=n;i++){int o=(a[i]+m-1)/m;if(o>=mx){mx=o;id=i;}}printf("%d\n",id);return 0; } /* 3 3 tsy */CF450B Jzzhu and Sequences
Description\text{Description}Description
有一個數列 fif_ifi?,給出 f1,f2f_1,f_2f1?,f2?,對于 i>2i>2i>2,滿足 fi=fi?1+fi+1f_i=f_{i-1}+f_{i+1}fi?=fi?1?+fi+1?.
求數列的第 nnn 項.
n≤109n\le10^9n≤109
Solution\text{Solution}Solution
移項:
fi+1=fi?fi?1f_{i+1}=f_{i}-f_{i-1}fi+1?=fi??fi?1?.
矩陣乘法即可.
Code\text{Code}Code
#include<bits/stdc++.h> using namespace std; #define ll long long //#define double long double #define debug(...) fprintf(stderr,__VA_ARGS__) const int N=1050; const int mod=1e9+7; inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f; } int n,m; struct matrix{ll a[3][3];int x,y;matrix(int xx,int yy):x(xx),y(yy){memset(a,0,sizeof(a));}matrix() {memset(a,0,sizeof(a));} }; matrix mul(matrix u,matrix v){matrix res(u.x,v.y);for(int k=1;k<=u.y;k++){for(int i=1;i<=u.x;i++){for(int j=1;j<=v.y;j++) (res.a[i][j]+=u.a[i][k]*v.a[k][j])%=mod;}}return res; } matrix ksm(matrix o,int k){matrix res(2,2);res.a[1][1]=res.a[2][2]=1;while(k){if(k&1) res=mul(res,o);o=mul(o,o);k>>=1;}return res; } matrix tr,ans; int main(){#ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout); #endifans.a[1][2]=(read()+mod)%mod;ans.a[1][1]=(read()+mod)%mod;ans.x=1;ans.y=2;n=read();if(n<=2){printf("%lld\n",ans.a[1][3-n]);return 0;}tr.x=tr.y=2;tr.a[1][1]=1;tr.a[1][2]=1;tr.a[2][1]=mod-1;tr.a[2][2]=0;ans=mul(ans,ksm(tr,n-2));printf("%lld\n",ans.a[1][1]);return 0; } /* 3 3 tsy */CF449A Jzzhu and Chocolate
Description\text{Description}Description
給出一個 N×MN \times MN×M 的矩陣,給 KKK 個操作,每次操作可以橫/豎切割矩陣,求 KKK 次切割,最大化最小塊的面積.
Solution\text{Solution}Solution
顯然要盡可能平均的切.
那么答案就是 ?nx?×?mk+2?x?\lfloor \dfrac{n}{x}\rfloor \times \lfloor \dfrac{m}{k+2-x}\rfloor?xn??×?k+2?xm??.
?nx?\lfloor \dfrac{n}{x}\rfloor?xn?? 只有 O(n)O(\sqrt n)O(n?) 中取值,整除分塊枚舉這些值,然后貪心的讓 xxx 盡可能的大即可.
需要開 longlong.
細節上,當 k+2?x≤0k+2-x\le0k+2?x≤0 時,要當成 111 處理.
Code\text{Code}Code
#include<bits/stdc++.h> using namespace std; #define ll long long //#define double long double #define debug(...) fprintf(stderr,__VA_ARGS__) const int N=1050; const int mod=1e9+7; inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f; } int n,m,k; ll ans; inline void check(int a){int b=k+2-a;if(b>m) return;if(b<=0) b=1;ans=max(ans,1ll*(n/a)*(m/b));return; } int main(){#ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout); #endifn=read();m=read();k=read();if(n+m<k+2){printf("-1");return 0;}for(int i=1;i<=n;){check(n/(n/i));i=n/(n/i)+1;}for(int i=1;i*i<=n;i++){if(n%i) continue;check(i);check(n/i);}printf("%lld\n",ans);return 0; } /* 3 3 tsy */CF449B Jzzhu and Cities
Description\text{Description}Description
nnn 個點,mmm 條帶權邊的無向圖,另外還有 kkk 條特殊邊,每條邊連接 111 和 iii 。 問最多可以刪除這kkk 條邊中的多少條,使得每個點到111 的最短距離不變.
Solution\text{Solution}Solution
我的做法是開兩個堆,一個堆是 Dijkstra 正常用的堆,第二個堆存所有特殊邊,優先從 dij 的堆轉移即可.
題解的方法是直接維護最短路的條數,感覺更加直觀.
Solution\text{Solution}Solution
#include<bits/stdc++.h> using namespace std; #define ll long long //#define double long double #define debug(...) fprintf(stderr,__VA_ARGS__) const int N=3e5+100; const int mod=1e9+7; inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f; } int n,m,k; struct node{int to,nxt,w; }p[N<<1]; int fi[N],cnt; inline void addline(int x,int y,int w){p[++cnt]=(node){y,fi[x],w};fi[x]=cnt;return; } struct edge{int id,val;bool operator < (const edge y)const{return val>y.val;} }; priority_queue<edge>Q; #define pr pair<ll,int> #define mkp make_pair priority_queue<pr,vector<pr>,greater<pr> >q; ll dis[N]; bool vis[N]; int ans; void dij(){memset(dis,0x3f,sizeof(dis));q.push(mkp(0,1));dis[1]=0;while(!q.empty()||!Q.empty()){int now;if(q.empty()||(!Q.empty()&&Q.top().val<q.top().first)){now=Q.top().id;int val=Q.top().val;Q.pop();if(vis[now]) continue;assert(dis[now]>val);dis[now]=val;++ans;}else{now=q.top().second;q.pop();if(vis[now]) continue;}vis[now]=1;for(int i=fi[now];~i;i=p[i].nxt){int to=p[i].to;if(dis[to]>dis[now]+p[i].w){dis[to]=dis[now]+p[i].w;q.push(mkp(dis[to],to));}} }return; } int main(){#ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout); #endifmemset(fi,-1,sizeof(fi));n=read();m=read();k=read();for(int i=1;i<=m;i++){int x=read(),y=read(),w=read();addline(x,y,w);addline(y,x,w);}for(int i=1;i<=k;i++){edge o={(int)read(),(int)read()};Q.push(o);}dij();printf("%d\n",k-ans);return 0; } /* 3 3 tsy */CF449C Jzzhu and Apples
Description\text{Description}Description
給出正整數 nnn,你要把 1?n1-n1?n 之間的正整數分成盡可能多組,使得每一組兩個數的最大公約數大于1;輸出能分成最多組的個數,并按任意順序輸出每組的兩個數.
Solution\text{Solution}Solution
樸素做法可以想到枚舉 gcdgcdgcd 把所有的倍數盡可能的配對.
考慮為什么這樣隨便選會不優.
就是當某次配對落單的最后也沒有配對,但是如果選擇其他某個元素落單,后面卻可以配對.
所以我們應該盡可能的選取后面容易配對的.
那么我們每次就令 2×g2\times g2×g 配對,最后在 g=2g=2g=2 的時候全都配對就行了.
這樣如果還有落單的,說明這些待定的是奇數個,那么肯定就會有落單的,不可能更優了.
Code\text{Code}Code
#include<bits/stdc++.h> using namespace std; #define ll long long //#define double long double #define debug(...) fprintf(stderr,__VA_ARGS__) const int N=1e5+100; const int mod=1e9+7; inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f; } int n,m,k; int q[N],st,ed; bool vis[N],jd[N]; int x[N],y[N],tot; int main(){#ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout); #endifn=read();for(int i=2;i<=n;i++){if(jd[i]) continue;for(int j=i+i;j<=n;j+=i) jd[j]=1;}for(int i=n;i>=2;i--){if(jd[i]) continue;st=1;ed=0;for(int j=i;j<=n;j+=i){if(!vis[j]) q[++ed]=j;}if(ed&1) swap(q[2],q[ed]);while(st<ed){++tot;x[tot]=q[st];vis[q[st++]]=1;y[tot]=q[st];vis[q[st++]]=1;}}printf("%d\n",tot);for(int i=1;i<=tot;i++) printf("%d %d\n",x[i],y[i]);return 0; } /* 3 3 tsy */CF449D Jzzhu and Numbers
Description\text{Description}Description
給出一個序列 a1...na_{1...n}a1...n?,求元素按位與結果等于 000 的非空子集選取方案個數.
n≤106,ai≤106n\le 10^6,a_i\le 10^6n≤106,ai?≤106.
Solution\text{Solution}Solution
神奇的題.
容易想到容斥,設 resires_iresi? 為與運算后至少有一個 111 的方案數.
那么答案就是:
ans=res0?res1+res2...ans=res_0-res_1+res_2...ans=res0??res1?+res2?...
但 resxres_xresx? 的值不易求解,所以轉而考慮求 fxf_xfx? 表示與運算后結果 www 滿足 w&x=xw\&x=xw&x=x 的方案數.
若有 numxnum_xnumx? 個 aia_iai? 滿足 ai&x=xa_i\&x=xai?&x=x ,那么就有
numx=2numx?1num_x=2^{num_x}-1numx?=2numx??1
也就是只能在這 numxnum_xnumx? 個數里選,且不能都不選.
那么關鍵就是求出 numxnum_xnumx?.
首先,對于每個 aia_iai?,令 numai++num_{a_i}++numai??++.
然后,按位枚舉 kkk ,然后若 xxx 的第 kkk 位是 111 ,就令 numx(1<<(k?1))←numxnum_{x^(1<<(k-1))}\gets num_xnumx(1<<(k?1))?←numx?.(換句話說就是轉移到把第 kkk 位扣掉后的數.
為什么這樣是對的?
首先,這樣轉移的顯然都是合法元素,且不會遺漏.
關鍵就是為什么這樣不會算重.
因為對于每個數對 (x,y),x&y=x(x,y),x\&y=x(x,y),x&y=x,numy→numxnum_y\to num_xnumy?→numx? 的轉移路徑是唯一的.
比如說 01101→0010001101\to0010001101→00100,就會且只會在枚舉第 111 位時 01101→0110001101\to 0110001101→01100,再在枚舉第 444 位時 01100→0010001100\to 0010001100→00100.
Code\text{Code}Code
#include<bits/stdc++.h> using namespace std; #define ll long long //#define double long double #define debug(...) fprintf(stderr,__VA_ARGS__) const int N=2e6+100; const int mod=1e9+7; inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f; } int n,m,k; int a[N],mi[25],f[N],bit[N]; ll ksm(ll x,ll k){ll res(1);while(k){if(k&1) res=res*x%mod;x=x*x%mod;k>>=1;}return res; } int main(){#ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout); #endifn=read();for(int i=1;i<=n;i++) a[i]=read(),f[a[i]]++;mi[0]=1;for(int i=1;i<=20;i++) mi[i]=mi[i-1]<<1;for(int j=20;j>=0;j--){for(int i=0;i<mi[20];i++){if(i&mi[j]) f[i^mi[j]]+=f[i];}}for(int i=1;i<mi[20];i++) bit[i]=bit[i-(i&-i)]+1;ll ans(0);for(int i=0;i<mi[20];i++){f[i]=(ksm(2,f[i])+mod-1)%mod;if(bit[i]&1) ans+=mod-f[i];else ans+=f[i];ans%=mod;}printf("%lld\n",ans);return 0; } /* 3 3 tsy */CF749E Inversions After Shuffle 題解
數學并不會但可以去看看這個
總結
以上是生活随笔為你收集整理的CodeForces:749(div1)750(div2)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 吾空推出新款凌云 X14 笔记本:i7-
- 下一篇: 模板:模拟退火