标签:
a Julyed
题意:n个单词,每天最多背m个单词,最少背多少天
分析:水题,不解释
#include<bits/stdc++.h> using namespace std; int main(){ int t,n,m; scanf("%d",&t); while(t--){ scanf("%d%d",&n,&m); int ans=n/m; if(n%m!=0) ans++; printf("%d\n",ans); } return 0; }
b. Fibonacci
题意:把n分解为Fibonacci数列的和,并且两个数不能连续
分析:其实两个数不能连续没有用,证明一下如果n=f1+f2+x,分类讨论下,x=f2,n那么n=2*f1+f2=f2+f3=f4,如果x=f3,那么n=f1+f2+f3=f1+f4,如果x==f4 n=f1+f2+f4=f3+f4=f5,如果n>f4
n=f3+x
所以n从大到小依次减Fibonacci,然后倒序输出就ok了
#include<bits/stdc++.h> using namespace std; const int maxn=105; int d[maxn],sz; void init(){ d[0]=d[1]=1; for(sz=2;;sz++){ d[sz]=d[sz-1]+d[sz-2]; if(d[sz]>=1e9) break; } } int main(){ init(); int t,n; scanf("%d",&t); while(t--){ scanf("%d",&n); stack<int> s; int tmp=n; for(int i=sz;i>0;i--) if(d[i]<=n){ s.push(d[i]); n-=d[i]; } printf("%d=",tmp); int a=s.top();s.pop(); printf("%d",a); while(!s.empty()){ a=s.top();s.pop(); printf("+%d",a); } puts(""); } return 0; }
c.Proxy
题意:0是本地计算机,n+1是服务器,1-n是代理服务器,给出每条线路的时间消耗,然后找到最短的0到n+1的路径,然后输出0处选择的第一个代理服务器,如如果不存在,输出-1,如果0-n+1直连且最短,输出0
分析:mdzz,读错题了,哎,说多了都是泪,都出的水题我们没出,dijkstra,把边倒着输入,然后找n+1-0的最短路,松弛操作记录前驱,特殊情况判断下就ok了
#include<bits/stdc++.h> using namespace std; const int maxn=1e5+5; const int INF=1e9; struct Edge{ int from,to,dist; Edge(int u,int v,int w):from(u),to(v),dist(w){} }; struct HeapNode{ int d,u; bool operator < (const HeapNode& r) const{ return d>r.d; } }; struct Dijkstra{ int n,m; vector<Edge> edges; vector<int> G[maxn]; bool done[maxn]; int d[maxn]; int p[maxn]; void init(int n){ this->n=n; for(int i=0;i<n;i++) G[i].clear(); edges.clear(); } void AddEdges(int from,int to,int dist){ edges.push_back(Edge(from,to,dist)); m=edges.size(); G[from].push_back(m-1); } void dijkstra(int s){ priority_queue<HeapNode> q; for(int i=0;i<n;i++) d[i]=INF; d[s]=0; memset(done,0,sizeof(done)); q.push((HeapNode){0,s}); while(!q.empty()){ HeapNode x=q.top();q.pop(); int u=x.u; if(done[u]) continue; done[u]=true; for(int i=0;i<G[u].size();i++){ Edge& e=edges[G[u][i]]; if(d[e.to]>d[u]+e.dist){ d[e.to]=d[u]+e.dist; p[e.to]=u; q.push((HeapNode){d[e.to],e.to}); } else if(d[e.to]==d[u]+e.dist) p[e.to]=min(p[e.to],G[u][i]); } } } }dijkstra; int main(){ int t; scanf("%d",&t); while(t--){ int n,m; scanf("%d%d",&n,&m); dijkstra.init(n+2); int u,v,w; while(m--){ scanf("%d%d%d",&u,&v,&w); dijkstra.AddEdges(v,u,w); } dijkstra.dijkstra(n+1); if(dijkstra.d[0]>=INF){ puts("-1"); continue; } if(dijkstra.p[0]==n+1){ puts("0"); continue; } printf("%d\n",dijkstra.p[0]); } return 0; }
d.Swiss-system tournament
2*n个人,每个人有一个初始的分数,和能力值,按照分数排序,分数相同,序号小的在前面,然后每次(1 2)(3 4),这样的两个人比较,能力值大的+1分,小的不变,最后输出排名为k的人的编号
分析:zz题,当时没几个出的,思路题,想不出来没办法,要注意到失败的人是有序,胜利的人是有序的,+1后依然是有序的,两个数组分别存,然后按归并的思想往里插,O(n)时间完成排序,总时间复杂度O(n*logn+r*n)
#include<bits/stdc++.h> using namespace std; const int maxn=1e5+5; int n,m,r; struct node{ int id,x,s; void read(int a,int b,int c){ id=a; x=b; s=c; } }v[maxn*2],v1[maxn],v2[maxn]; bool cmp(node a,node b){ if(a.x==b.x) return a.id<b.id; return a.x>b.x; } void solve(){ int l=0,r=0; for(int i=0;i<n;i+=2){ int a=i,b=i+1; if(v[a].s<v[b].s||(v[a].s==v[b].s&&v[a].id>v[b].id)) swap(a,b); v1[l++].read(v[a].id,v[a].x+1,v[a].s); v2[r++].read(v[b].id,v[b].x,v[b].s); } int a=0,b=0,c=0; while(a<l||b<r){ if((b>=r)||(a<l&&(v1[a].x>v2[b].x||(v1[a].x==v2[b].x&&v1[a].id<v2[b].id)))) v[c++]=v1[a++]; else v[c++]=v2[b++]; //printf("%d ",v[c-1].x); } // puts(""); } int main(){ int t; scanf("%d",&t); while(t--){ scanf("%d%d%d",&n,&r,&m); n*=2; for(int i=0;i<n;i++){ scanf("%d",&v[i].x); v[i].id=i; } for(int i=0;i<n;i++) scanf("%d",&v[i].s); sort(v,v+n,cmp); while(r--) solve(); printf("%d\n",v[m-1].id+1); } return 0; }
e.The Binding of Isaac
题意:有一些房间,周围都是空地,求只与一个房间相邻的空地数
分析:这个题都出了吧,看到第一眼以为是个搜索,没想到就一水题,n,m周围都搞成空地,然后输入就行,之间判断每个空地周围房间数
#include<bits/stdc++.h> using namespace std; const int maxn=105; const int dx[]={0,0,1,-1}; const int dy[]={1,-1,0,0}; char g[maxn][maxn]; int n,m; int judge(int x,int y){ int count=0; for(int i=0;i<4;i++){ int nx=x+dx[i]; int ny=y+dy[i]; if(nx<0||nx>n+1||ny<0||ny>m+1) continue; if(g[nx][ny]==‘#‘) count++; } return count==1?1:0; } int main(){ int t; scanf("%d",&t); while(t--){ scanf("%d%d",&n,&m);getchar(); for(int i=0;i<=n+1;i++)g[i][0]=g[i][m+1]=‘.‘; for(int i=0;i<=m+1;i++)g[0][i]=g[n+1][i]=‘.‘; for(int i=1;i<=n;i++){ scanf("%s",g[i]+1); getchar(); } int ans=0; for(int i=0;i<=n+1;i++) for(int j=0;j<=m+1;j++) if(g[i][j]==‘#‘) continue; else ans+=judge(i,j); printf("%d\n",ans); } return 0; }
f.Feed the monkey
题意:三个东西分别有n1,n2,n3个,每天取一个物品,但是三种物品连续取得不得超过d1,d2,d3个,问有多少取方案
分析:当时一看,算了下转态50^4*3,1e7多点,没问题,时间足够,而且非常多的状态达不到,就采用了记忆化搜索,当时脑残了,有个错就是找不到,遗憾,出来就找到了,悲哀,莫过于赛后过题
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int mod=1e9+7; int dp[55][55][55][55][3]; int n[3],num[3]; int dfs(int a,int b,int c,int d,int e){ int& z=dp[a][b][c][d][e]; if(a==0&&b==0&&c==0)return z=1; if(z!=-1) return z; ll ans=0; for(int i=0;i<3;i++){ if(i==0&&a==0)continue; else if(i==1&&b==0)continue; else if(i==2&&c==0)continue; int p; if(e==i){ p=d+1; if(p>num[i])continue; } else p=1; if(i==0) ans+=dfs(a-1,b,c,p,i); else if(i==1) ans+=dfs(a,b-1,c,p,i); else if(i==2) ans+=dfs(a,b,c-1,p,i); ans%=mod; } return z=(int)ans; } int main(){ int t; cin>>t; while(t--){ for(int i=0;i<3;i++) cin>>n[i]; for(int i=0;i<3;i++) cin>>num[i]; ll ans=0; memset(dp,-1,sizeof(dp)); for(int i=0;i<3;i++){ if(n[i]==0) continue; if(i==0) ans+=dfs(n[0]-1,n[1],n[2],1,i); else if(i==1) ans+=dfs(n[0],n[1]-1,n[2],1,i); else if(i==2) ans+=dfs(n[0],n[1],n[2]-1,1,i); ans%=mod; } cout<<ans<<endl; } return 0; }
g.Triple Nim
题意:nim游戏都玩过吧,把n个数字分成三堆,两人采取最佳策略,先手输
分析:先手输,也就是说三堆异或为0,然后我就往二进制上想,先想到奇数无解,因为最后的那个1,没有其他的1和他去^,然后由此我想到对应位的1只能分解为下一位的两个1,当时没想到组合数,我蒙了一个公式,决定赌一发,wa了,然后我继续考虑n中二进制有4个1的情况,然后想到一个神奇的式子(3^3-1)/2,一试,2 3个1的时候也成立,然后就搞了,a了,赛后想了下原理,比如20,二进制分解为11110,第四位必须放两个1,然后就是剩下三个1的放法了,每个1有三种方法,也就是3^3,减去第三个数什么都没得到的情况,然后(1,3,4)和(1,4,3)是同一种情况,所以/2
#include<bits/stdc++.h> using namespace std; int main(){ int t,n; scanf("%d",&t); while(t--){ scanf("%d",&n); if(n&1){ puts("0"); continue; } int count=-1; for(int i=1;i<=31;i++) if(n&(1<<i)) count++; long long ans=pow(3,count)-1; ans/=2; printf("%lld\n",ans); } return 0; }
h.Memory Leak
题意:
分析:
iRock Paper Scissors
题意:
分析:
j Execution of Paladin
题意:http://hs.178.com/201606/259352896164.html
分析:分析毛啊,没玩过炉石的伤不起啊,就这样吧,队友写的
#include<cstdio> #include<queue> #include<functional> #include <iostream> #include <vector> #include <cstring> #include <cmath> #include <algorithm> using namespace std; string s; int main() { int t; scanf("%d",&t); while(t--) { int n,m; scanf("%d%d",&n,&m); getchar(); int a=0,b=0,c=0; for(int i=0;i<n;i++) { getline(cin,s); if(s[0]==‘M‘) a++; if(s[0]==‘B‘) b++; if(s[0]==‘O‘) c++; } int cnt=2*(b+c)+2*a*(b+c)+(n-1)*c; if(cnt>=m) printf("Mrghllghghllghg!\n"); else printf("Tell you a joke, the execution of Paladin.\n"); } }
k.Reversed Words
题意:不用说了,一看就知道,直接上代码
#include<bits/stdc++.h> using namespace std; string s; int main(){ int t; scanf("%d",&t);getchar(); while(t--){ getline(cin,s); stack<string> ans; string tmp=""; int len=s.length(); for(int i=len-1;i>=0;i--) if(s[i]!=‘ ‘) tmp+=s[i]; else{ ans.push(tmp); tmp=""; } cout<<tmp; while(!ans.empty()){ tmp=ans.top(); ans.pop(); cout<<" "<<tmp; } cout<<endl; } return 0; }
l Password
题意,6种操作,用最少的次数,把第一个数变成第二个数
分析:都是6位数,感觉记忆化搜索就可以搞,10^6*6,不大
标签:
原文地址:http://www.cnblogs.com/jihe/p/5573378.html