2016-2017 ACM Central Region of Russia Quarterfinal Programming Contest
A. Fried Fish
题意:有N条鱼,有一个同时可以煎k条鱼的锅,鱼两个面都要煎;
分析:k*2个面要煎,是否有一种方式可以让锅没有空闲,当时我举了几个例子,确实可以找到,没有证明,注意n<k的情况
#include <iostream> #include <cstdio> #include <cstring> using namespace std; int main() { freopen("INPUT.TXT","r",stdin); freopen("OUTPUT.TXT","w",stdout); int x,y; while(scanf("%d%d",&x,&y)!= EOF) { if(2*x<=y) printf("2\n"); else { if((2*x)%y==0) printf("%d\n",(2*x)/y); else printf("%d\n",(2*x)/y+1); } } return 0; }
B. Hanoi tower
题意:用给出的汉诺塔算法,求出第一次相同时的步数;
分析:
网上有一个公式:先求出n层从A到B的步数:d(n)=d(n-1)*2+1
然后:ans(n)= d(n/3*2-1)+d(n/3-1)+1
勉强这个方案可以看懂,的确要比ans(n)=d(n/32)+d(n/3)或者 2d(n/3) 要小,
但是,最后有一个特判,不是很懂;
回到原题,直接根据给出的算法,打表求解,前几项分别是:
2 9 38 135 542 2079
直接给出公式把:强烈推荐python 写大整数
a = [0]*105 #print a a[1] = 2 a[2] = 9 deta = 97 for i in range(3,103): if i%2==1: a[i] = a[i-1]*4+2 else: a[i] = a[i-1]+deta deta = 16*deta - 15 cin = open("input.txt","r") cout = open("output.txt","w") n = int(int(cin.read())/3) cout.write(str(a[n]))
打表程序:
#include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <iostream> #include <vector> #include <queue> #include <set> using namespace std; typedef long long ll; int k; int ans; int num[3]; void hanoi(char x,char y,char z,int n) { if(n>0) { hanoi(x,z,y,n-1); printf("------->%d: %d%d%d\n",k++,--num[x-'a'],++num[y-'a'],num[z-'a']); //k++; //num[x-'a']--; //num[y-'a']++; //if(num[x-'a']==num[y-'a']&&num[y-'a']==num[z-'a']) { // ans = k; //return ; //} hanoi(z,y,x,n-1); } } int main() { freopen("output.txt","w",stdout); int n; scanf("%d",&n); k = 1; num[0] = n; hanoi('a','b','c',n); printf("%d\n",ans); return 0; }
D. Weather Station
题意:有8个方向,给出一个字符串,求这个字符串可能是几种方案合成的
分析:乘法原理,d(i) 是前 i 项字符的方案数,当i+1 个字符串可能模棱两可,那么这里就有两种可能,于是:d(i+1)= d(i)*2
#include <bits/stdc++.h> using namespace std; const int maxn = 100000 + 5; char str[maxn]; const int MOD = 1000000000+7; int main() { freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); scanf("%s",str); int len = strlen(str); int ans = 1; for(int i=0;i<len;i++) { if(str[i]=='N'&&str[i+1]=='E') ans = ans*2%MOD; else if(str[i]=='S'&&str[i+1]=='W') ans = ans*2%MOD; else if(str[i]=='S'&&str[i+1]=='E') ans = ans*2%MOD; else if(str[i]=='N'&&str[i+1]=='W') ans = ans*2%MOD; } printf("%d\n",ans); return 0; }
E. Cupcakes
题意:有n个学生,来排队吃蛋糕k个,领完后又到队列后面可以继续吃,每个学生最多能吃a_i个,有一个大胃王,每次都吃完a_i,现在大家想让他吃的时候恰好没有蛋糕了,求是不是可能;
分析:贪心极端情况,当轮到大胃王吃的时候,如果,前面的人最少,最多能吃[l,r]个,k在个区间,于是就可以做到;
#include <bits/stdc++.h> using namespace std; const int maxn = 100000+5; long long a[maxn]; int main() { freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); int n; long long k; scanf("%d%lld",&n,&k); long long x = 0; int flag = -1; for(int i=0;i<n;i++) { scanf("%lld",&a[i]); if(a[i]>x) { flag = i; x = max(x,a[i]); } } long long l = 0,r=0; for(int i=0;i<flag;i++) { l ++; r +=a[i]; } if(l<=k&&r>=k) { puts("YES"); return 0; } while(l<=r) { l+=x; r+=x; for(int i=flag+1;i<n;i++) { l++; r = r + a[i]; } for(int i=0;i<flag;i++) { l++; r = r + a[i]; } if(l<=k&&r>=k) { puts("YES"); return 0; } else if(l>k) break; } puts("KEK"); return 0; }
G. Sphenic numbers
题意:一个数是否是三个素数的乘积
分析:直接质因数分解
#include<bits/stdc++.h> using namespace std; const int maxn = 10467397 + 105; vector<int> primes; bool bo[maxn+5]; int prime_table() { int i,j,cnt=0; bo[0]=bo[1]=true; for(i=2; i<=sqrt(maxn*1.0); i++) if(!bo[i]) { j=i*i; for(; j<=maxn; j+=i) bo[j]=true; } for(i=0; i<=maxn; i++) if(!bo[i]) primes.push_back(i); return primes.size(); } bool add_int(int n){ int e = 0; for(int i = 0; i < primes.size(); i++){ bool f = true; while(n % primes[i] == 0){ n /= primes[i]; if(f){ f = false; e++; } } if(n == 1) return e == 3; } } int main() { // freopen("in.txt", "r", stdin); freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout); int n; prime_table(); scanf("%d", &n); puts(add_int(n) ? "YES" : "NO"); return 0; }
H. Non-random numbers
题意:生成一个n位的随机数,有多少种数,有三条规则:
- 没有前导零
- 第 i 位 不是 i
- n 位
分析:第一位8种,后面9种,再后面10种,不用写大整数.
#include <bits/stdc++.h> using namespace std; int main() { freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); int n; scanf("%d",&n); unsigned long long ans = 1; if(n<=9) { n--; ans = 8; for(int i=0;i<n;i++) ans = ans *9; cout<<ans<<endl; } else { ans = 8; for(int i=0;i<8;i++) ans = ans*9; cout<<ans; for(int i=10;i<=n;i++) printf("%d",0); puts(""); } return 0; }
J. Architect of Your Own Fortune
题意:有两种票,可以折叠起来拼成一种超级幸运票,求最多能匹配多少张?
分析:最大匹配
#include <bits/stdc++.h> using namespace std; const int maxn = 500+5; struct BPM { int n,m; vector<int> G[maxn]; int left[maxn]; bool T[maxn]; int right[maxn]; bool S[maxn]; void init(int n,int m) { this->n = n; this->m = m; for(int i=0; i<n; i++) G[i].clear(); } void AddEdge(int u,int v) { G[u].push_back(v); } bool match(int u) { S[u] = true; for(int i=0; i<G[u].size(); i++) { int v = G[u][i]; if(!T[v]) { T[v] = true; if(left[v]==-1||match(left[v])) { left[v] = u; right[u] = v; return true; } } } return false; } int solve() { memset(left,-1,sizeof(left)); memset(right,-1,sizeof(right)); int ans = 0; for(int u=0; u<n; u++) { memset(S,0,sizeof(S)); memset(T,0,sizeof(T)); if(match(u)) ans++; } return ans; } } sol; char a[maxn][10]; char b[maxn][10]; int main() { freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); int n,m; scanf("%d%d",&n,&m); sol.init(n,m); for(int i=0; i<n; i++) scanf("%s",a[i]); for(int i=0; i<m; i++) scanf("%s",b[i]); for(int i=0; i<n; i++) { int aa = a[i][0]-'0' + a[i][1] -'0' + a[i][2]-'0'; for(int j=0; j<m; j++) { int bb = b[j][3]-'0'+b[j][4]-'0'+b[j][5]-'0'; if(aa==bb) sol.AddEdge(i,j); } } for(int i=0; i<n; i++) { int aa = a[i][3]-'0' + a[i][4] -'0' + a[i][5]-'0'; for(int j=0; j<m; j++) { int bb = b[j][0]-'0' + b[j][1] -'0' + b[j][2]-'0'; if(aa==bb) sol.AddEdge(i,j); } } printf("%d\n",sol.solve()); for(int i=0;i<n;i++) { if(sol.right[i]!=-1) { int j = sol.right[i]; int aa = a[i][0]-'0' + a[i][1] -'0' + a[i][2]-'0'; int bb = b[j][3]-'0'+b[j][4]-'0'+b[j][5]-'0'; if(aa==bb) printf("AT %s %s\n",a[i],b[j]); else printf("TA %s %s\n",b[j],a[i]); } } return 0; }
来源:https://www.cnblogs.com/TreeDream/p/7101066.html