ICPC2017南宁站题解(A,E,F,H,I,J,L,M)
VP比赛时间:2020-07-23: 7 / 13 Rank: 35 / 228
VP通过:A,E,F,H,I,J,L
赛后补题:M
感想:这场对大数要求挺多(2道题F和L),我队Java选手很给力。然后银牌题大概是E和M(M那时候没信心去挑战毕竟在银首,但是赛后补题发现是一个floyd+裸最大独立集,还是简单题。E是偏向思维的概率数学)。H是大模拟,I题是无脑dfs模拟。就这场和icpc2019南昌来说,我感觉银牌图论题可能要求并不是很高,要有信心去挑战银牌题吧。毕竟感觉铜牌图论撑死就是生成树和最短路了(真的吗?)
A.Abiyoyo
第一签到题,Anonytt,懒得说:
#include<bits/stdc++.h> #define ll long long #define rep(i,a,n) for(int i=a;i<=n;i++) #define per(i,n,a) for(int i=n;i>=a;i--) #define endl '\n' #define eps 0.000000001 #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) #define IO ios::sync_with_stdio(false);cin.tie(0); using namespace std; const int INF=0x3f3f3f3f; const ll inf=0x3f3f3f3f3f3f3f3f; const int mod=1e9+7; const int maxn=1e5+5; int main(){ int T;cin>>T; while(T--){ int n;cin>>n; rep(i,1,n){ puts("Abiyoyo, Abiyoyo."); } rep(i,1,2){ puts("Abiyoyo, yo yoyo yo yoyo."); } } }
E. The Champion
银牌题,Libm,我不会。
#include <bits/stdc++.h> #define ll unsigned long long #define endl '\n' using namespace std; double p; ll fa[65]; double cal(int r,ll k){ double ans=1; if(r==1){ if(k==1) ans=1; else ans=1-p; } else if(k<=fa[r-1]){ double cur=1; while(k<=fa[r-1]){ cur=cur*p; r--; if(r==1) break; } ans=(1-p)+p-cur+cur*cal(r,k); } else{ while(k>fa[r-1]){ k-=(fa[r-1]); r--; ans*=(1-p); if(r==1) break; } ans*=cal(r,k); } return ans; } double solve(int r,ll k){ double ans=1; if(r==1){ if(k==1) ans=p; else ans=1-p; return ans; } if(k==fa[r-1]+1){ for(int i=1;i<r;i++) ans*=p; ans*=(1-p); } else if(k<fa[r-1]+1){ for(int i=1;i<r;i++) ans*=p; double now=cal(r-1,k); ans=ans*(now*p+(1-now)*(1-p)); } else{ while(k>fa[r-1]+1){ k-=fa[r-1]; r--; ans*=(1-p); } ans*=solve(r,k); } return ans; } int main(){ ios::sync_with_stdio(false);cin.tie(0); int T;cin>>T; fa[0]=1; for(int i=1;i<=63;i++) fa[i]=fa[i-1]*2; while(T--){ int r; ll k; cin>>r>>k>>p; double ans=solve(r,k); printf("%.6lf\n",ans); } }
F. The Chosen One
签到java大数题,kele
import java.math.BigInteger; import java.util.Scanner; public class Main{ public static void main(String[] args){ Scanner input = new Scanner(System.in); int t = input.nextInt(); while (t > 0) { BigInteger m = input.nextBigInteger(); BigInteger ans = (new BigInteger("2")).pow(m.bitLength() - 1); System.out.println(ans); t--; } input.close(); } }
H.The Game of Life
铜牌大模拟,我提供我(Anonytt)的写法,因为是个无限大的图,但是最多就321次衍生,所以实际上最终图的大小是不会超过(2*321+n)*(2*321+m),为了方便所以我就把初始点全部行列+400。然后记录当前是活着的点,把他们存在set里,然后并对活着的周边8个点的cnt进行统计。每次更新,用queue队列来缩减时间。
#include<bits/stdc++.h> #define ll long long #define rep(i,a,n) for(int i=a;i<=n;i++) #define per(i,n,a) for(int i=n;i>=a;i--) #define endl '\n' #define eps 0.000000001 #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) #define IO ios::sync_with_stdio(false);cin.tie(0); using namespace std; const int INF=0x3f3f3f3f; const ll inf=0x3f3f3f3f3f3f3f3f; const int mod=1e9+7; const int maxn=1e5+5; int a[900][900],cnt[900][900]; int dx[9]={1,-1,0,0,1,1,-1,-1}; int dy[9]={0,0,1,-1,1,-1,1,-1}; int n,m; int main(){ int T;scanf("%d",&T); while(T--){ mem(a,0);mem(cnt,0); scanf("%d%d",&n,&m); int maxx=0,id=0; set<pair<int,int> >s; rep(i,1,n){ rep(j,1,m){ char xx;cin>>xx; if(xx=='#'){ int u=i+400,v=j+400; a[u][v]=1;++maxx; rep(o,0,7){ int x=u+dx[o],y=v+dy[o]; cnt[x][y]+=1; s.insert({x,y}); } s.insert({u,v}); } else a[i+400][j+400]=0; } } int c; rep(t,1,321){ int cur=0; queue<pair<int,int> >q; for(auto it:s){ int x=it.first,y=it.second; if(cnt[x][y]==3&&!a[x][y]) {a[x][y]=1;++cur;q.push({x,y});} else if((cnt[x][y]==2&&a[x][y])||(cnt[x][y]==3&&a[x][y])) {a[x][y]=1;++cur;q.push({x,y});} else if((cnt[x][y]<=1&&a[x][y])||(cnt[x][y]>=4&&a[x][y])) {a[x][y]=0;} cnt[x][y]=0; } if(cur>maxx) {maxx=cur,id=t;} if(t==321) c=cur; s.clear(); if(t<321){ while(!q.empty()){ auto now=q.front();q.pop(); int x=now.first,y=now.second; s.insert({x,y}); } queue<pair<int,int> >que; for(auto it:s){ int xx=it.first,yy=it.second; rep(o,0,7){ int x=xx+dx[o],y=yy+dy[o]; cnt[x][y]+=1;que.push({x,y}); } } while(!que.empty()){ auto now=que.front();que.pop(); int x=now.first,y=now.second; s.insert({x,y}); } } } cout<<id<<" "<<maxx<<" "<<c<<endl; } }
I.Rake It In
铜牌无脑暴力dfs。Anonytt,时间复杂度大概=200*pow(9,6)≈1e8,刚好能擦过,所以就无脑暴力吧
#include<bits/stdc++.h> #define ll long long #define rep(i,a,n) for(int i=a;i<=n;i++) #define per(i,n,a) for(int i=n;i>=a;i--) #define endl '\n' #define eps 0.000000001 #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) #define IO ios::sync_with_stdio(false);cin.tie(0); using namespace std; const int INF=0x3f3f3f3f; const ll inf=0x3f3f3f3f3f3f3f3f; const int mod=1e9+7; const int maxn=1e5+5; int a[5][5],k; int find(int x,int y){ int res=0; res+=a[x][y]+a[x+1][y]+a[x][y+1]+a[x+1][y+1]; return res; } void rot(int x,int y){ int temp=a[x][y]; a[x][y]=a[x][y+1]; a[x][y+1]=a[x+1][y+1]; a[x+1][y+1]=a[x+1][y]; a[x+1][y]=temp; } void back(int x,int y){ int temp=a[x][y]; a[x][y]=a[x+1][y]; a[x+1][y]=a[x+1][y+1]; a[x+1][y+1]=a[x][y+1]; a[x][y+1]=temp; } int dfs(int t){ if(t==2*k){ int ans=INF,x,y; rep(i,1,3){ rep(j,1,3){ ans=min(ans,find(i,j)); } } return ans; } else{ if(t%2==1){ int ans=0,x,y; rep(i,1,3){ rep(j,1,3){ rot(i,j); ans=max(ans,find(i,j)+dfs(t+1)); back(i,j); } } return ans; } if(t%2==0){ int ans=INF,x,y; rep(i,1,3){ rep(j,1,3){ rot(i,j); ans=min(ans,find(i,j)+dfs(t+1)); back(i,j); } } return ans; } } } int main(){ int T;scanf("%d",&T); while(T--){ scanf("%d",&k); rep(i,1,4){ rep(j,1,4){ scanf("%d",&a[i][j]); } } cout<<dfs(1)<<endl; } }
J. Rearrangement
签到,Anonytt
#include<bits/stdc++.h> #define ll long long #define rep(i,a,n) for(int i=a;i<=n;i++) #define per(i,n,a) for(int i=n;i>=a;i--) #define endl '\n' #define eps 0.000000001 #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) #define IO ios::sync_with_stdio(false);cin.tie(0); using namespace std; const int INF=0x3f3f3f3f; const ll inf=0x3f3f3f3f3f3f3f3f; const int mod=1e9+7; const int maxn=1e5+5; int a[2*maxn]; int main(){ int T;scanf("%d",&T); while(T--){ int n;scanf("%d",&n); int cnt1=0,cnt2=0,cnt3=0; rep(i,1,2*n){ scanf("%d",&a[i]); if(a[i]%3==0) cnt3++; if(a[i]%3==1) cnt1++; if(a[i]%3==2) cnt2++; } if(cnt3>n) {puts("NO");continue;} if(cnt3==n){puts("YES");continue;} else if(cnt3==0){ if(cnt1&&cnt2) puts("NO"); else puts("YES"); } else if(cnt3==1){ if(cnt1&&cnt2) puts("NO"); else puts("YES"); } else if(cnt3==2){ if(cnt1%2==0&&cnt2%2==0){puts("NO");continue;} else puts("YES"); } else puts("YES"); } }
L. Twice Equation
大数java+板子,kele
import java.math.BigInteger; import java.util.Scanner; public class Main{ public static void main(String[] args){ Scanner input = new Scanner(System.in); int t = input.nextInt(); BigInteger[] a = new BigInteger[1000]; a[0] = BigInteger.ZERO; a[1] = BigInteger.valueOf(3); BigInteger ke = new BigInteger("6"); BigInteger le = new BigInteger("2"); for(int i = 2; i <= 400; i++){ a[i] = ((a[i - 1].multiply(ke)).subtract(a[i - 2])).add(le); // System.out.println(a[i]); } for(int i = 0; i < t; i++) { boolean flag = false; BigInteger L = input.nextBigInteger(); for(int j = 0; j <= 400; j++){ if(a[j].compareTo(L) >= 0){ System.out.println(a[j]); flag = true; break; } } if(!flag) System.out.println(-1); } input.close(); } }
M.The Maximum Unreachable Node Set
(赛后通过Anonytt),其实就是一个最大独立集的问题,不过需要之前用floyd转化,其实看出最大独立集不难,关键是想到floyd转化
#include<bits/stdc++.h> #define ll long long #define rep(i,a,n) for(int i=a;i<=n;i++) #define per(i,n,a) for(int i=n;i>=a;i--) #define endl '\n' #define eps 0.000000001 #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) #define IO ios::sync_with_stdio(false);cin.tie(0); using namespace std; const int INF=0x3f3f3f3f; const ll inf=0x3f3f3f3f3f3f3f3f; const int mod=1e9+7; const int maxn=1e5+5; int n,m,line[505][505],used[505],match[505]; int find(int x){ rep(i,1,n){ if(!used[i]&&line[x][i]){ used[i]=true; if(match[i]==0||find(match[i])){ match[i]=x; return true; } } } return false; } int main(){ int T;scanf("%d",&T); while(T--){ scanf("%d%d",&n,&m); mem(line,0);mem(match,0); rep(i,1,m){ int u,v;scanf("%d%d",&u,&v); line[u][v]=1; } rep(k,1,n){ rep(i,1,n){ rep(j,1,n){ if(line[i][k]&&line[k][j]) line[i][j]=1; } } } int ans=0; rep(i,1,n){ mem(used,0); if(find(i)) ++ans; } printf("%d\n",n-ans); } }
再接再厉啊,希望现场icpc区域赛能有银牌qwq