2017-2018 ACM-ICPC German Collegiate Programming Contest (GCPC 2017)_组队训练
2017-2018 ACM-ICPC German Collegiate Programming Contest (GCPC 2017)
B Buildings
C Joyride
D Pants On Fire
F Plug It In!
G Water Testing
I Überwatch
K You Are Fired!
B Buildings
题意:给你m面墙,每面墙有n*n个格子,给你c种颜色,求有多种涂色方法(注意房子是一个正多边形,即旋转之后不能一样)
题解:polya计数裸题,
#include<bits/stdc++.h> #define ll long long int using namespace std; const int mod = 1e9+7; ll qpow(ll n,ll m) { ll res=1; ll k=n; while(m) { if(m&1)res=res*k%mod; k=k*k%mod; m/=2; } return res; } int main() { int n,m,c; cin>>n>>m>>c; ll sum = 0; ll g=qpow(c,n*n); for(int i=1;i<=m;i++) { sum+=(qpow(g,__gcd(i,m))%mod); sum = sum%mod; } sum=sum*qpow(m,mod-2)%mod; cout<<sum%mod<<endl; }
C Joyride
题意:你在游乐园玩耍,你从1出发在x分钟内你要回到1,这中间有n个娱乐设施,m条人行道,你走人行道的时间要t分钟,m行输入两点之间的人行横道,n个游乐
设施所要花费的时间和价格,问你在x分钟内你可以花的最小钱为多少,x分钟都要用满,游乐设施可以多次玩耍。
题解:按花费钱的数量跑最短路,dist[v][k]dist[v][k] 表示在 kk 时刻走到点 vv 最少花费 dist[v][t]dist[v][t] 元。最短路变形,用队列来优化。
#include<bits/stdc++.h> #define ll long long using namespace std; const int maxn = 1010; int x; int n,m,w; int t[maxn],p[maxn]; struct Edge{ int u,v,w; Edge(){} Edge(int _u,int _v){u=_u, v=_v;} }; vector<Edge> E; vector<int> G[maxn]; void addedge(int u,int v) { E.push_back(Edge(u,v)); G[u].push_back(E.size()-1); } struct Qnode { int v,k,d; Qnode(){} Qnode(int _v,int _k,int _d) { v=_v, k=_k, d=_d; } bool operator<(const Qnode& oth)const { return d>oth.d; } }; int dist[maxn][maxn]; bool vis[maxn][maxn]; void dijkstra() { memset(dist,0x3f,sizeof(dist)); memset(vis,0,sizeof(vis)); priority_queue<Qnode> Q; if(t[1]<=x) dist[1][t[1]]=p[1]; else return; Q.push(Qnode(1,t[1],p[1])); while(!Q.empty()) { int u=Q.top().v, k=Q.top().k; Q.pop(); if(vis[u][k]) continue; vis[u][k]=1; if(k+t[u]<=x && dist[u][k+t[u]]>dist[u][k]+p[u]) { dist[u][k+t[u]]=dist[u][k]+p[u]; Q.push(Qnode(u,k+t[u],dist[u][k+t[u]])); } for(int i=0;i<G[u].size();i++) { Edge &e=E[G[u][i]]; int v=e.v; if(k+w+t[v]>x) continue; if(!vis[v][k+w+t[v]] && dist[v][k+w+t[v]]>dist[u][k]+p[v]) { dist[v][k+w+t[v]]=dist[u][k]+p[v]; Q.push(Qnode(v,k+w+t[v],dist[v][k+w+t[v]])); } } } } int main() { cin>>x>>n>>m>>w; for(int i=1,u,v;i<=m;i++) { cin>>u>>v; addedge(u,v); addedge(v,u); } for(int i=1;i<=n;i++) cin>>t[i]>>p[i]; dijkstra(); if(vis[1][x]) cout<<dist[1][x]<<endl; else cout<<"It is a trap."<<endl; }
D Pants On Fire
题意:给你n条定理,输入格式确定,求m条问题的正确性。
题解:传递闭包。
#include<bits/stdc++.h> #include<iostream> #include<algorithm> #include<cstring> #include<vector> #define ll long long int #define mem(a,b) memset(a,b,sizeof a) using namespace std; const int INF = 0x3f3f3f3f; map<string,int>mp; int mm[404][404]; int n,m; int ans; void Floyd() { for(int k=1;k<=ans;k++) { for(int i=1;i<=ans;i++) { for(int j=1;j<=ans;j++) { mm[i][j] = min(mm[i][j],mm[i][k]+mm[k][j]); } } } } int main() { cin>>n>>m; ans = 1; mp.clear(); for(int i=1;i<=2*n;i++) { for(int j=1;j<=2*n;j++) { if(i!=j) mm[i][j] = INF; } } for(int i=1;i<=n;i++) { string a,b,c,d,e; cin>>a>>b>>c>>e>>d; if(!mp[a]) { mp[a] = ans; ans++; } if(!mp[d]) { mp[d] = ans; ans++; } mm[mp[a]][mp[d]] = 1; } Floyd(); while(m--) { string a,b,c,d,e; cin>>a>>b>>c>>e>>d; if(mp[a]==0||mp[d]==0) { puts("Pants on Fire"); continue; } if(mm[mp[a]][mp[d]]==INF&&mm[mp[d]][mp[a]]==INF) { puts("Pants on Fire"); } else if(mm[mp[a]][mp[d]]!=INF&&mm[mp[d]][mp[a]]==INF) { puts("Fact"); } else{ puts("Alternative Fact"); } } }
F Plug It In!
题意:n个插座,m个电器,下面k行匹配关系,一个一般的插座只能插一个电器,你可以使一个的插座插三个同一电器,求最大匹配数。
题解:先按插座的的型号进行匈牙利匹配,然后再枚举每一个型号的插座看看能不能再插电器,即再进行匈牙利匹配,二分图匹配。
#include<bits/stdc++.h> #define ll long long int #define mem(a,b) memset(a,b,sizeof a) using namespace std; int n,m,k; int girl[1600],used[1600],love[1600][1600]; int tmp[1600]; void init() { memset(girl,0,sizeof girl); memset(love,0,sizeof love); memset(used,0,sizeof used); } bool find(int x){ int i,j; for (j=1;j<=n;j++){ if (love[x][j]==1 && used[j]==0) { used[j]=1; if (girl[j]==0 || find(girl[j])) { girl[j]=x; return true; } } } return false; } int find2(int h) { for(int i=1;i<=n;i++) { if(used[i]||!love[h][i])continue; used[i]=1; if(tmp[i]!=h&&(tmp[i]==0||find2(tmp[i]))) { tmp[i]=h;return 1; } } return 0; } int main() { init(); cin>>m>>n>>k; for(int i=1;i<=k;i++) { int x,y; cin>>x>>y; //mp[x[i]]++; love[x][y] = 1; } int ans = 0; for(int j=1;j<=m;j++) { mem(used,0); if(find(j)) ans++; } //cout<<ans<<endl; int ma=0; for(int i=1;i<=m;i++) { int add=0; for(int j=1;j<=n;j++)tmp[j]=girl[j]; memset(used,0,sizeof(used)); if(find2(i)){ add++; memset(used,0,sizeof(used)); if(find2(i)) { add++; } } ma=max(ma,add); } //cout<<ma<<" "<<ans<<endl; printf("%d\n",ma+ans); }
G Water Testing
题意:按顺序给出边界的点,看看在封闭的图形内有多少个整数点。
题解: 皮克定理裸体,皮克定理:S=a+b/2−1,S表示多边形的面积
a表示多边形内的整数点
b表示多边形边界上的整数点。
//#include<bits/stdc++.h> #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<string> #include<vector> #include<stack> #include<bitset> #include<cstdlib> #include<cmath> #include<set> #include<list> #include<deque> #include<map> #include<queue> #define ll long long #define MOD 1000000007 #define pdd pair<double,double> #define mem(a,x) memset(a,x,sizeof(a)) #define IO ios::sync_with_stdio(false);cin.tie(0) using namespace std; const long long INF = 1e18+5; const int inf = 0x3f3f3f3f; const double eps=1e-6; const int maxn=200005; const double pi=acos(-1); inline char nc() {static char buf[1000000],*p1=buf,*p2=buf;return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;} inline void read(int &sum) {char ch=nc();sum=0;while(!(ch>='0'&&ch<='9')) ch=nc();while(ch>='0'&&ch<='9') sum=(sum<<3)+(sum<<1)+(ch-48),ch=nc();} ll gcd(ll a,ll b) { if(b == 0) return a; return gcd(b,a%b); } ll x[maxn],y[maxn]; int n; int main() { int n; cin >> n; ll x0,y0,x1,y1,S = 0; cin >> x[1] >> y[1]; x0 = x[1]; y0 = y[1]; x1 = x[1]; y1 = y[1]; for(int i=2;i<=n;i++) { cin >> x[i] >> y[i]; S += (x1*y[i]-y1*x[i]); x1 = x[i]; y1 = y[i]; } S += (x1*y0-y1*x0); ll sum = 0; // cout<<S<<endl; for(int i=1;i<=n;i++){ if(i<n){ ll aa=abs(x[i+1]-x[i]); ll bb=abs(y[i+1]-y[i]); sum+=gcd(aa,bb)-1; }else{ ll aa=abs(x[1]-x[n]); ll bb=abs(y[1]-y[n]); sum+=gcd(aa,bb)-1; } } sum+=n; printf("%lld\n",abs(S)/2+1-sum/2); }
I Überwatch
签到题:
#include<bits/stdc++.h> #define ll long long int using namespace std; int x[300030]; int dp[300030]; int main() { int n,m; cin>>n>>m; for(int i=1;i<=n;i++) { cin>>x[i]; } for(int i=1;i<=n;i++) { dp[i] = dp[i-1]; if(i>=m+1) { dp[i] = max(dp[i-m]+x[i],dp[i]); } } int maxx = 0; for(int i=1;i<=n;i++) { maxx = max(maxx,dp[i]); } cout<<maxx<<endl; }
K:
签到题
#include<bits/stdc++.h> #define ll long long using namespace std; map<string,ll>mp; typedef pair<string, ll> PAIR; bool cmp(const PAIR &left,const PAIR &right) { return left.second > right.second; } int main() { ll n,d,k; cin>>n>>d>>k; ll ans = 0; for(int i=1;i<=n;i++) { string s; ll x; cin>>s>>x; mp[s] = x; } vector<PAIR> vec(mp.begin(),mp.end()); sort(vec.begin(),vec.end(),cmp); for (vector<PAIR>::iterator it = vec.begin(); it != vec.end(); ++it) { if(d<=0) break; else{ d-=it->second; ans++; } } if(ans>k||(ans==n&&d>0)) { puts("impossible"); } else{ cout<<ans<<endl; ll q = 0; for (vector<PAIR>::iterator it = vec.begin(); it != vec.end(); ++it) { if(q>=ans) break; else{ cout<<it->first<<", YOU ARE FIRED!"<<endl; q++; } } } }