gym101667 2017-2018 ACM-ICPC, Asia Daejeon Regional Contest 简单题解
A:不会
B:暴力搜索,枚举每一次操作的情况,稍微剪枝,避免重复记录即可
#include<bits/stdc++.h> #include <vector> #define ll long long #define rep(ii,a,b) for(int ii=a;ii<=b;++ii) #define per(ii,a,b) for(int ii=b;ii>=a;--ii) #define forn(i,x,g,e) for(int i=g[x];i;i=e[i].next) #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0) #define ull unsigned long long #define fi first #define se second #define mp make_pair #define pii pair<ll,ll> #define all(x) x.begin(),x.end() #define show(x) cout<<#x<<"="<<x<<endl #define show2(x,y) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<endl #define show3(x,y,z) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl #define show4(w,x,y,z) cout<<#w<<"="<<w<<" "<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl #define show5(v,w,x,y,z) cout<<#v<<"="<<v<<" "<<#w<<"="<<w<<" "<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl #define showa(x,a,b) cout<<#x<<": ";rep(i,a,b) cout<<x[i]<<' ';cout<<endl using namespace std;//head const int maxn = 7; int pz[maxn][maxn]; int lst[maxn]; ll res; int ex,ey; unordered_set<ll> win; int check() { int f1 = 0, f2 = 0; for(int i = 1; i <= 4; i++) { for(int j = 1; j <= 2; j++) { if(pz[i][j] == 1 && pz[i][j+1] == 1 && pz[i][j+2] == 1) f1++; if(pz[i][j] == 2 && pz[i][j+1] == 2 && pz[i][j+2] == 2) f2++; } } for(int j = 1; j <= 4; j++) for(int i = 1; i <= 2; i++) { if(pz[i][j] == 1 && pz[i+1][j] == 1 && pz[i+2][j] == 1) f1++; if(pz[i][j] == 2 && pz[i+1][j] == 2 && pz[i+2][j] == 2) f2++; } for(int i = 1; i <= 2; i++) { for(int j = 1; j <= 2; j++) { if(pz[i][j] == 1 && pz[i+1][j+1] == 1 && pz[i+2][j+2] == 1) f1++; if(pz[i][j] == 2 && pz[i+1][j+1] == 2 && pz[i+2][j+2] == 2) f2++; } } for(int i = 1; i <= 2; i++) { for(int j = 3; j <= 4; j++) { if(pz[i][j] == 1 && pz[i+1][j-1] == 1 && pz[i+2][j-2] == 1) f1++; if(pz[i][j] == 2 && pz[i+1][j-1] == 2 && pz[i+2][j-2] == 2) f2++; } } if(f1 != 0) return 1; return f2 == 0 ? 0 : 2; } int all; void dfs(int p,int x,int y){ if(pz[ex][ey]==1) return ; int tmp=check(); if(tmp==1) return ; if(pz[ex][ey]==2&&p==0&&ex==x&&ey==y){ if(tmp==2){ ll st=3; rep(i,1,4)rep(j,1,4){ st*=3; st+=pz[i][j]; } win.insert(st); return ; } } if(tmp==2) return ; if(all==0) return ; rep(i,1,4){ if(lst[i]==0) continue; lst[i]--; all--; int pos=1; while(pz[pos][i]!=0) pos++; pz[pos][i]=1+p; dfs(1-p,pos,i); pz[pos][i]=0; lst[i]++; all++; } } int ans[6][6][6]; int main() { memset(pz,0,sizeof pz); int a,b,c;cin>>a>>b>>c; rep(_i,1,4)lst[_i]=4; pz[1][a]=1;lst[a]=3; ex=b,ey=c; all=15; dfs(1,1,a); cout<<win.size(); }
C:重定向边,记忆化搜索求DAG上最长路即可
#include<bits/stdc++.h> #include <vector> #define ll long long #define rep(ii,a,b) for(int ii=a;ii<=b;++ii) #define per(ii,a,b) for(int ii=b;ii>=a;--ii) #define forn(i,x,g,e) for(int i=g[x];i;i=e[i].next) #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0) #define ull unsigned long long #define fi first #define se second #define mp make_pair #define pii pair<ll,ll> #define all(x) x.begin(),x.end() #define show(x) cout<<#x<<"="<<x<<endl #define show2(x,y) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<endl #define show3(x,y,z) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl #define show4(w,x,y,z) cout<<#w<<"="<<w<<" "<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl #define show5(v,w,x,y,z) cout<<#v<<"="<<v<<" "<<#w<<"="<<w<<" "<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl #define showa(x,a,b) cout<<#x<<": ";rep(i,a,b) cout<<x[i]<<' ';cout<<endl using namespace std;//head const int maxn=3e5+10,maxm=2e6+10; const ll INF=0x3f3f3f3f,mod=1e9+7; int casn,n,m,k; int d[maxn],dis[maxn],vis[maxn]; pii e[maxn]; int ans; vector<int> g[maxn]; int dfs(int now){ if(dis[now]) return dis[now]; int res=1; for(int to:g[now]){ res=max(res,dfs(to)+1); } return dis[now]=res; } int main(){ cin>>n>>m; rep(i,1,m){ int a,b;cin>>a>>b; e[i]=make_pair(a,b); d[a]++,d[b]++; } rep(i,1,m){ int a=e[i].fi,b=e[i].se; if(d[a]==d[b]) continue; if(d[a]>d[b]) swap(a,b); g[b].push_back(a); // vis[a]=1; } rep(i,1,n) if(!vis[i])dfs(i); rep(i,1,n) k=max(dis[i],k); // showa(dis,1,n); cout<<k<<endl; return 0; }
D:暴力
#include<bits/stdc++.h> #include <vector> #define ll long long #define rep(ii,a,b) for(int ii=a;ii<=b;++ii) #define per(ii,a,b) for(int ii=b;ii>=a;--ii) #define forn(i,x,g,e) for(int i=g[x];i;i=e[i].next) #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0) #define ull unsigned long long #define fi first #define se second #define mp make_pair #define pii pair<ll,ll> #define all(x) x.begin(),x.end() #define show(x) cout<<#x<<"="<<x<<endl #define show2(x,y) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<endl #define show3(x,y,z) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl #define show4(w,x,y,z) cout<<#w<<"="<<w<<" "<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl #define show5(v,w,x,y,z) cout<<#v<<"="<<v<<" "<<#w<<"="<<w<<" "<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl #define showa(x,a,b) cout<<#x<<": ";rep(i,a,b) cout<<x[i]<<' ';cout<<endl using namespace std;//head const int maxn=1e3+10,maxm=2e6+10; const ll INF=0x3f3f3f3f,mod=1e9+7; int casn,n,m,k; bool vis[maxn]; int f(ll x) { int res = 0; while(x) { int a = x%10; res += a*a; x /= 10; } return res; } int main(){ ll n; cin >> n; if(n == 1) { cout << "HAPPY\n"; return 0; } memset(vis, false, sizeof vis); int now = f(n); vis[now] = true; while(now != 1) { now = f(now); if(vis[now]) { cout << "UNHAPPY\n"; return 0; } vis[now] = 1; } cout << "HAPPY\n"; return 0; }
E:做法有点像枚举边求最小环
枚举每一条边,把所有边权比它小的边放入图中,然后以这两个边为源点和汇点跑最小割即可
#include<bits/stdc++.h> #include <vector> #define ll long long #define rep(ii,a,b) for(int ii=a;ii<=b;++ii) #define per(ii,a,b) for(int ii=b;ii>=a;--ii) #define forn(i,x,g,e) for(int i=g[x];i;i=e[i].next) #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0) #define ull unsigned long long #define fi first #define se second #define mp make_pair #define pii pair<ll,ll> #define all(x) x.begin(),x.end() #define show(x) cout<<#x<<"="<<x<<endl #define show2(x,y) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<endl #define show3(x,y,z) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl #define show4(w,x,y,z) cout<<#w<<"="<<w<<" "<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl #define show5(v,w,x,y,z) cout<<#v<<"="<<v<<" "<<#w<<"="<<w<<" "<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl #define showa(x,a,b) cout<<#x<<": ";rep(i,a,b) cout<<x[i]<<' ';cout<<endl using namespace std;//head const int maxn=1e6+10,maxm=2e6+10; const ll INF=0x3f3f3f3f,mod=1e9+7; int casn,n,m,k; template<typename T>class mxf{public: struct node{int to,next;T cap;}e[maxm<<1]; int cur[maxn],head[maxn],dis[maxn],gap[maxn]; int nume=1,s,t,tot; void init(int n){ rep(i,0,n) head[i]=gap[i]=dis[i]=0; nume=1; } void add(int a,int b,T c){ e[++nume]={b,head[a],c};head[a]=nume; e[++nume]={a,head[b],0};head[b]=nume; } T dfs(int now,T flow=INF){ if (now==t||!flow) return flow; T use=0,tmp; int d=dis[now]-1,to; for (int &i=cur[now];i;i=e[i].next) { if(dis[to=e[i].to]==d&&(tmp=e[i].cap)){ e[i].cap-=(tmp=dfs(to,min(flow-use,tmp))); e[i^1].cap+=tmp; if((use+=tmp)==flow) return use; } } if (!--gap[dis[now]]) dis[s]=tot+1; ++gap[++dis[now]]; cur[now]=head[now]; return use; } T getflow(int ss,int tt,int n,T ans=0){ tot=n;s=ss;t=tt;gap[0]=tot; memcpy(cur,head,(tot+1)<<2); while(dis[s]<=tot) ans+=dfs(s); return ans; } }; mxf<int> net; struct node{int a,b,c;}e[maxn]; bool cmp(node x,node y){ return x.c<y.c; } int main() { cin>>n>>m; rep(i,1,m){ cin>>e[i].a>>e[i].b>>e[i].c; } sort(e+1,e+1+m,cmp); ll ans=0; rep(i,1,m){ net.init(n); int s=e[i].a,t=e[i].b; rep(j,1,m){ if(j==i) continue; if(e[j].c>=e[i].c) break; net.add(e[j].a,e[j].b,1); net.add(e[j].b,e[j].a,1); } int tmp=net.getflow(s,t,n); ans+=tmp; } cout<<ans<<endl; return 0; } // auto _start=chrono::high_resolution_clock::now(); // auto _end=chrono::high_resolution_clock::now(); // cerr<<"elapsed time: "<<chrono::duration<double,milli>(_end-_start).count()<<" ms\n";
F:递归分解,找规律
#include<bits/stdc++.h> #include <vector> #define ll long long #define rep(ii,a,b) for(int ii=a;ii<=b;++ii) #define per(ii,a,b) for(int ii=b;ii>=a;--ii) #define forn(i,x,g,e) for(int i=g[x];i;i=e[i].next) #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0) #define ull unsigned long long #define fi first #define se second #define mp make_pair #define pii pair<ll,ll> #define all(x) x.begin(),x.end() #define show(x) cout<<#x<<"="<<x<<endl #define show2(x,y) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<endl #define show3(x,y,z) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl #define show4(w,x,y,z) cout<<#w<<"="<<w<<" "<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl #define show5(v,w,x,y,z) cout<<#v<<"="<<v<<" "<<#w<<"="<<w<<" "<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl #define showa(x,a,b) cout<<#x<<": ";rep(i,a,b) cout<<x[i]<<' ';cout<<endl using namespace std;//head pair<ll, ll> f(ll k, ll step) { ll len = (k), Size = len*len/4; if(k == 2) { if(step == 0) return make_pair(1, 1); else if(step == 1) return make_pair(1, 2); else if(step == 2) return make_pair(2, 2); else return make_pair(2, 1); } int num = step/Size; step = step%Size; if(num == 0) { pair<ll, ll> tmp = f(k/2, step); swap(tmp.fi, tmp.se); return tmp; } else if(num == 1) { pair<ll, ll> tmp = f(k/2, step); tmp.se += len/2; return tmp; } else if(num == 2) { pair<ll, ll> tmp = f(k/2, step); tmp.fi += len/2; tmp.se += len/2; return tmp; } else { pair<ll, ll> tmp = f(k/2, step); swap(tmp.fi, tmp.se); ll a = len/2-tmp.fi+1, b = len/2-tmp.se+1; return make_pair(a+len/2, b); } } int main() { std::ios::sync_with_stdio(false); ll k; ll step; cin >> k >> step; step--; pair<ll, ll> t = f(k, step); cout << t.fi << " " << t.se << "\n"; return 0; }
G:不会
H:一开始想了假算法,卡了很久,后来才写的fft
#include<bits/stdc++.h> #define ll long long #define rep(i, a, b) for(int i = a; i <= b; i++) #define IO std::ios::sync_with_stdio(false) using namespace std; const int maxn=8e6+20,maxm=8e3+10; const double pi=acos(-1.0); struct cp{double x,y;}a[maxn],b[maxn]; cp operator*(cp a,cp b){return {a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x};} cp operator+(cp a,cp b){return {a.x+b.x,a.y+b.y};} cp operator-(cp a,cp b){return {a.x-b.x,a.y-b.y};} class fourier{public: int rev[maxn],len,pw; void init(int n){ len=1,pw=0; while(len<=n) len<<=1,pw++; rep(i,0,len-1) rev[i]=0; rep(i,0,len-1) rev[i]=(rev[i>>1]>>1)|((i&1)<<(pw-1)); } void transform(cp*a,int flag){ rep(i,0,len-1) if(i<rev[i]) swap(a[i],a[rev[i]]); for(int mid=1;mid<len;mid<<=1){ cp wn={cos(pi/mid),flag*sin(pi/mid)}; for(int r=mid<<1,j=0;j<len;j+=r){ cp t={1,0}; for(int k=0;k<mid;k++,t=t*wn){ cp x=a[j+k],y=t*a[mid+j+k]; a[j+k]=x+y,a[j+k+mid]=x-y; } } } if(flag==-1) rep(i,0,len-1) a[i].x/=len; } }fft; char st[] = {'R', 'S', 'P'}; int n, m; string s, t; int ans[maxn]; void solve(char ch, char ch1) { for(int i = 0; i <= fft.len; i++) a[i].x = b[i].x = a[i].y = b[i].y = 0; for(int i = 1; i <= m; i++) if(t[m-i+1] == ch) b[i].x = 1; for(int i = 1; i <= n; i++) if(s[i] == ch1) a[i].x = 1; fft.transform(a, 1); fft.transform(b, 1); for(int i = 0; i < fft.len; i++) { a[i] = a[i]*b[i]; } fft.transform(a, -1); for(int l = 0; l < n; l++) { ans[l] += (int)(a[l+m+1].x+0.5); } } int main() { std::ios::sync_with_stdio(false); cin >> n >> m >> s >> t; s = " " + s; t = " " + t; fft.init(n+m); solve('R', 'S'); solve('S', 'P'); solve('P', 'R'); int res = 0; for(int i = 0; i < n; i++) res = max(res, ans[i]); cout << res << "\n"; return 0; } /** 12 4 RSPPSSSRRPPR RRRR 12 3 RRRRRRRRRRRR SSS 12 4 PPPRRRRRRRRR RSSS 12 4 RRRRRRRRRSSS RRRS **/
I:KMP,枚举K即可
#include<bits/stdc++.h> #include <vector> #define ll long long #define rep(ii,a,b) for(int ii=a;ii<=b;++ii) #define per(ii,a,b) for(int ii=b;ii>=a;--ii) #define forn(i,x,g,e) for(int i=g[x];i;i=e[i].next) #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0) #define ull unsigned long long #define fi first #define se second #define mp make_pair #define pii pair<ll,ll> #define all(x) x.begin(),x.end() #define show(x) cout<<#x<<"="<<x<<endl #define show2(x,y) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<endl #define show3(x,y,z) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl #define show4(w,x,y,z) cout<<#w<<"="<<w<<" "<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl #define show5(v,w,x,y,z) cout<<#v<<"="<<v<<" "<<#w<<"="<<w<<" "<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl #define showa(x,a,b) cout<<#x<<": ";rep(i,a,b) cout<<x[i]<<' ';cout<<endl using namespace std;//head const int maxn=1e6+10,maxm=2e6+10; const ll INF=0x3f3f3f3f,mod=1e9+7; int casn,n,m,k; class prefix{public: int p[maxn],lens; int *s; void init(int *_s,int _lens){ s=_s,lens=_lens; rep(i,0,lens-1) p[i]=0; p[0]=-1; int now=0,pos=-1; while(now<lens) if(pos==-1||s[now]==s[pos]) p[++now]=++pos; else pos=p[pos]; } vector<int> find(int *t,int lent){ int now,pos=0; vector<int> ans; while(now<lent) { if(pos==-1||t[now]==s[pos]) pos++,now++; else pos=p[pos]; if(pos==lens) pos=p[pos],ans.push_back(now-lens); } return ans; } }kmp; int a[maxn]; int main() {IO; cin>>n; per(i,0,n-1){ cin>>a[i]; } kmp.init(a,n); int ans1=INF,ans2=INF; rep(i,1,n){ int t=i-kmp.p[i]; if(ans1+ans2==t+n-i){ if(t<ans2) { ans1=n-i;ans2=t; } }else if(ans1+ans2>t+n-i){ ans1=n-i;ans2=t; } } cout<<ans1<<' '<<ans2<<endl; }
J:不会
K:构造
#include<bits/stdc++.h> #include <vector> #define ll long long #define rep(ii,a,b) for(int ii=a;ii<=b;++ii) #define per(ii,a,b) for(int ii=b;ii>=a;--ii) #define forn(i,x,g,e) for(int i=g[x];i;i=e[i].next) #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0) #define ull unsigned long long #define fi first #define se second #define mp make_pair #define pii pair<ll,ll> #define all(x) x.begin(),x.end() #define show(x) cout<<#x<<"="<<x<<endl #define show2(x,y) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<endl #define show3(x,y,z) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl #define show4(w,x,y,z) cout<<#w<<"="<<w<<" "<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl #define show5(v,w,x,y,z) cout<<#v<<"="<<v<<" "<<#w<<"="<<w<<" "<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl #define showa(x,a,b) cout<<#x<<": ";rep(i,a,b) cout<<x[i]<<' ';cout<<endl using namespace std;//head const int maxn = 1e4+10; int a[maxn]; int main() { std::ios::sync_with_stdio(false); int n; cin >> n; for(int i = 1; i <= n; i++) { int x; cin >> x >> a[i]; } int nowx = 0, nowy = 0, l = 0, r = 0, u = 0, d = 0; int vx = 1, vy = 0; cout << "1 "; r = 1; nowx = 1; for(int i = 1; i < n; i++) { if(a[i] == 1) { if(vx == 1 && vy == 0) { vx = 0, vy = 1; cout << u+1-nowy << " "; nowy = u+1; u++; } else if(vx == 0 && vy == 1) { vx = -1, vy = 0; cout << nowx-(l-1) << " "; nowx = l-1; l = l-1; } else if(vx == -1 && vy == 0) { vx = 0, vy = -1; cout << nowy-(d-1) << " "; nowy = d-1; d--; } else { vx = 1, vy = 0; cout << r+1-nowx << " "; nowx = r+1; r++; } } else if(a[i] == -1){ if(vx == 1 && vy == 0) { vx = 0, vy = -1; cout << nowy-(d-1) << " "; nowy = d-1; d--; } else if(vx == 0 && vy == 1) { vx = 1, vy = 0; cout << r+1-nowx << " "; nowx = r+1; r++; } else if(vx == -1 && vy == 0) { vx = 0, vy = 1; cout << u+1-nowy << " "; nowy = u+1; u++; } else { vx = -1, vy = 0; cout << nowx-(l-1) << " "; nowx = l-1; l--; } } } }
L:赛后补的,枚举天数进行dp,上限大概是n^3天
#include<bits/stdc++.h> #define ll long long using namespace std; const int maxn = 55; ll dp[3][maxn][maxn*maxn*maxn], a[3][maxn]; vector<pair<int, int> > E[3][maxn]; int n[3], m[3], goal[3]; int main() { std::ios::sync_with_stdio(false); int p, all = 1; cin >> p; for(int k = 0; k < p; k++) { cin >> n[k] >> m[k]; all *= n[k]; for(int i = 1; i <= n[k]; i++) cin >> a[k][i]; for(int i = 1; i <= m[k]; i++) { int x, y, c; cin >> x >> y >> c; //E[k][x].push_back(make_pair(y, c)); E[k][y].push_back(make_pair(x, c)); //对每个点要知道谁能到他 反向存图 } cin >> goal[k]; } for(int i = 0; i < p; i++) { for(int j = 0; j <= n[i]; j++) { for(int k = 0; k <= all; k++) { dp[i][j][k] = 1e18; } } } #define fi first #define se second for(int k = 0; k < p; k++) { // cout << "@@\n"; dp[k][1][0] = 0; for(int j = 1; j <= all; j++) { for(int i = 1; i <= n[k]; i++) { dp[k][i][j] = min(dp[k][i][j], dp[k][i][j-1]+a[k][i]); for(auto it : E[k][i]) { int v = it.fi, c = it.se; dp[k][i][j] = min(dp[k][i][j], dp[k][v][j-1]+c); } } } } ll ans = 1e18; for(int i = 1; i <= all; i++) { ll tmp = 0; // cout << "---i = " << i << endl; for(int k = 0; k < p; k++) { // cout << "k = " << k << " dp = " << dp[k][goal[k]][i] << endl; tmp += dp[k][goal[k]][i]; } ans = min(ans, tmp); } cout << ans << "\n"; }