The German Collegiate Programming Contest 2017
B - Building
给一个m各面的多边形柱体,每一侧面有n*n个格子,现在对这些格子染色,看有多少种方式使得多面柱体无论如何旋转都不会与另一个一样。
#include <bits/stdc++.h> using namespace std; typedef long long ll; #define mod 1000000007 ll n,m,c; ll quickly_pow(ll x,ll y){ ll ans=1; while(y){ if(y&1) ans=ans*x%mod; y>>=1; x=x*x%mod; } return ans%mod; } int main(){ scanf("%lld%lld%lld",&n,&m,&c); ll pos=quickly_pow(c,n*n); ll ans=0; for(ll i=1;i<=m;i++){ ans+=quickly_pow(pos,__gcd(i,m)); ans%=mod; } printf("%lld\n",ans*quickly_pow(m,mod-2)%mod); return 0; }
C - Joyride
有m条边n个点,经过每个点耗时t,花费p,经过每一条边花费ti,现在问你总共时间x,确保花完,在回到出口,花费最小。
bfs+剪枝
#include <bits/stdc++.h> using namespace std; typedef long long ll; #define INF 0x3f3f3f3f vector<int>v[1006]; vector<pair<int,int> >cost(1005); struct node{ int u,t,w; node(int u,int t,int w):u(u),t(t),w(w){} bool operator<(const node &a) const{ return w>a.w; } }; int x,n,m,t; int dis[1006][1006]; void bfs(){ memset(dis,INF,sizeof(dis)); if(x-cost[1].first<0) return ; priority_queue<node>q; dis[1][x-cost[1].first]=cost[1].second; q.push(node(1,x-cost[1].first,cost[1].second)); while(!q.empty()){ node e=q.top(); q.pop(); if(e.w>dis[e.u][e.t]) continue; if(e.t-cost[e.u].first>=0){ if(dis[e.u][e.t-cost[e.u].first]>(dis[e.u][e.t]+cost[e.u].second)){ dis[e.u][e.t-cost[e.u].first]=dis[e.u][e.t]+cost[e.u].second; q.push(node(e.u,e.t-cost[e.u].first,dis[e.u][e.t-cost[e.u].first])); } } for(int i=0;i<v[e.u].size();i++){ if(e.t-t-cost[v[e.u][i]].first>=0){ if(dis[v[e.u][i]][e.t-cost[v[e.u][i]].first-t]>(dis[e.u][e.t]+cost[v[e.u][i]].second)){ dis[v[e.u][i]][e.t-cost[v[e.u][i]].first-t]=dis[e.u][e.t]+cost[v[e.u][i]].second; q.push(node(v[e.u][i],e.t-cost[v[e.u][i]].first-t,dis[v[e.u][i]][e.t-cost[v[e.u][i]].first-t])); } } } } } int main(){ scanf("%d%d%d%d",&x,&n,&m,&t); for(int i=0;i<m;i++){ int u,to; scanf("%d%d",&u,&to); v[u].push_back(to); v[to].push_back(u); } for(int i=1;i<=n;i++) scanf("%d%d",&cost[i].first,&cost[i].second); bfs(); if(dis[1][0]==INF) printf("It is a trap.\n"); else printf("%d\n",dis[1][0]); return 0; }
D - Pants On Fire
根据前面n条句子,判断后面句子是否正确,传递性。
离散化+flyod
#include <bits/stdc++.h> using namespace std; map<string,int>m; int n,q,ans=0; int vis[406][406]; string u,v,s; int main(){ scanf("%d%d",&n,&q); for(int i=0;i<n;i++){ cin>>u>>s>>s>>s>>v; vis[m[u]?m[u]:(m[u]=++ans)][m[v]?m[v]:(m[v]=++ans)]=1; } for(int k=1;k<=ans;k++) for(int i=1;i<=ans;i++) for(int j=1;j<=ans;j++) if(vis[i][k] && vis[k][j]) vis[i][j]=1; while(q--){ cin>>u>>s>>s>>s>>v; if(vis[m[u]][m[v]]) printf("Fact\n"); else if(vis[m[v]][m[u]]) printf("Alternative Fact\n"); else printf("Pants on Fire\n"); } return 0; }
G - Water Testing
皮克定理,求多边形内部点的数量
#include <bits/stdc++.h> using namespace std; typedef long long ll; struct Point{ ll x,y; }p[100005]; ll n; ll operator * (Point a,Point b){return a.x*b.y-a.y*b.x;} ll cal(Point a,Point b){ if(a.x==b.x) return abs(b.y-a.y)-1; if(a.y==b.y) return abs(b.x-a.x)-1; return __gcd(abs(b.y-a.y),abs(a.x-b.x))-1; } ll area(){ ll s=0; for(int i=0;i<n;i++) s+=p[i]*p[(i+1)%n]; return abs(s); } ll solve(){ ll ans=n; for(int i=0;i<n;i++) ans+=cal(p[i],p[(i+1)%n]); return ans-2; } int main(){ scanf("%lld",&n); for(int i=0;i<n;i++) scanf("%lld%lld",&p[i].x,&p[i].y); printf("%lld\n",(area()-solve())/2); return 0; }
I - Uberwatch
K - You Are Fired!
在开除不超过k个人的情况下,使得工资大于等于d
优先队列
#include <bits/stdc++.h> #define ll long long using namespace std; const int AX = 1e4 + 666 ; struct Node{ string s ; ll v ; bool operator < (const Node &ch )const{ return v < ch.v ; } }a[AX]; int main(){ ll n,d,k; priority_queue<Node>q; scanf("%lld%lld%lld",&n,&d,&k); for(int i=0;i<n;i++){ string s; ll c; cin>>s>>c; q.push((Node){s,c}); } int ans=0; while(!q.empty() && d>0 && ans<k){ Node e=q.top(); q.pop(); a[ans++]=e; //printf("%lld\n",e.v); d-=e.v; } if(d>0) printf("impossible\n"); else{ printf("%d\n",ans); for(int i=0;i<ans;i++){ cout<<a[i].s<<","; cout<<" YOU ARE FIRED!"<<endl; } } return 0 ; }