2017西电第一次省赛选拔赛补题
https://vjudge.net/contest/161101#overview
A.判断B是否能整除A的每一个素因子。
#include<bits/stdc++.h> using namespace std; int prime[1000005],vis[1000005] = {0}; long long a,b; int main() { ios::sync_with_stdio(false); int T,z = 0; cin >> T; int cnt = 0; for(int i = 2;i <= 1000000;i++) { if(!vis[i]) prime[++cnt] = i; for(int j = 1;i*prime[j] <= 1000000 && j <= cnt;j++) { vis[prime[j]*i] = 1; if(i%prime[j] == 0) break; } } while(T--) { cin >> a >> b; cout << "Case #" << ++z << ": "; int flag = 0; for(int i = 1;(long long)prime[i]*prime[i] <= a;i++) { if(a%prime[i] == 0) { while(a%prime[i] == 0) a /= prime[i]; if(b%prime[i]) flag = 1; } } if(b%a) flag = 1; if(flag) cout << "NO" << endl; else cout << "YES" << endl; } return 0; }
B.显然,最优解是每次选择一个人就把他HP耗尽。假设只有两个人,则
先攻击第一个人消耗:DPS1HP1+DPS2(HP1+HP2)
先攻击第二个人消耗:DPS2HP2+DPS1(HP1+HP2)
可以得出当DPS1/HP1 > DPS2/HP2时,攻击第一个人消耗小。
由此推广到n个人的情况,按DPSi/HPi排序即可。
#include<bits/stdc++.h> using namespace std; int n; struct xx { int hp,dps; friend bool operator <(xx a,xx b) { return a.dps*b.hp > a.hp*b.dps; } }a[25]; int main() { ios::sync_with_stdio(false); while(cin >> n) { for(int i = 1;i <= n;i++) cin >> a[i].dps >> a[i].hp; sort(a+1,a+1+n); int ans = 0,sum = 0; for(int i = 1;i <= n;i++) { sum += a[i].hp; ans += sum*a[i].dps; } cout << ans << endl; } return 0; }
C.先把前一半的密文翻译乘明码,KMP求后半的在前半的最长前缀。
#include<bits/stdc++.h> using namespace std; string s,ss; int nextt[200005]; map<char,char> mp; void get_next(string s) { int len = s.length(); int i = 0,j = -1; nextt[0] = -1; while(i < len) { if(j == -1 || s[i] == s[j]) nextt[++i] = ++j; else j = nextt[j]; } } int main() { int T; cin >> T; while(T--) { cin >> ss >> s; for(int i = 0;i < ss.length();i++) mp[ss[i]] = i+'a'; int len = s.length(),endd = (len+1)/2; string sss = s; for(int i = 0;i < endd;i++) s[i] = mp[s[i]]; s.insert(endd,1,'+'); get_next(s); int cnt = len-nextt[len+1]; for(int i = 0;i < cnt;i++) cout << sss[i]; for(int i = 0;i < cnt;i++) cout << mp[sss[i]]; cout << endl; } return 0; }
D.set模拟,注意连续在一个点吃的时候,方向不改变。
#include<bits/stdc++.h> using namespace std; int n,m,cnt[100005]; set<int> s; set<int>::iterator it; int main() { ios::sync_with_stdio(false); int T,z = 0; cin >> T; while(T--) { s.clear(); memset(cnt,0,sizeof(cnt)); cin >> n >> m; int dir = 2,now = 0; long long ans = 0; while(m--) { int a,b; cin >> a; if(a == 0) { cin >> b; if(cnt[b] == 0) s.insert(b); cnt[b]++; } else { if(s.size() == 0) continue; it = s.lower_bound(now); int x = 1e9,y = 1e9; if(it != s.end()) y = *it-now; if(it != s.begin()) { it--; x = now-*it; it++; } if(it != s.end() && now == *it); else if(x < y || x == y && dir == 1) { it--; ans += x; dir = 1; } else { ans += y; dir = 2; } now = *it; cnt[*it]--; if(cnt[*it] == 0) s.erase(it); } } cout << "Case " << ++z << ": " << ans << endl; } }
E.因为每两个点之间有且只有一条单向边,拓扑排序判断是否存在环即可,有环肯定有三元环。
#include<bits/stdc++.h> using namespace std; int n,in[2005]; string s; vector<int> v[2005]; bool topsort() { int cnt = 0; while(cnt < n) { int t; for(t = 1;t <= n;t++) { if(in[t] == 0) break; } if(t == n+1) return 1; in[t]--; cnt++; for(int i = 0;i < v[t].size();i++) { in[v[t][i]]--; } } return 0; } int main() { ios::sync_with_stdio(false); int T,z = 0; cin >> T; while(T--) { cin >> n; for(int i = 1;i <= n;i++) v[i].clear(); memset(in,0,sizeof(in)); for(int i = 1;i <= n;i++) { cin >> s; s = " "+s; for(int j = 1;j < s.length();j++) { if(s[j] == '1') in[j]++; v[i].push_back(j); } } cout << "Case #" << ++z << ": "; if(topsort()) cout << "Yes" << endl; else cout << "No" << endl; } return 0; }
F.逆序建树就可以了。
#include<iostream> using namespace std; struct xx { xx *l,*r; char x; }*root; string s[10005]; void insertt(xx *&p,char x) { if(p == NULL) { p = new xx; p->l = NULL; p->r = NULL; p->x = x; return; } if(p->x > x) insertt(p->l,x); else insertt(p->r,x); } void printff(xx *p) { if(!p) return; cout << p->x; printff(p->l); printff(p->r); } int main() { ios::sync_with_stdio(false); while(1) { int n = 0; while(cin >> s[++n] && s[n] != "*" && s[n] != "$"); root = NULL; for(int i = n-1;i >= 1;i--) { for(int j = 0;j < s[i].length();j++) insertt(root,s[i][j]); } printff(root); cout << endl; if(s[n] == "$") break; } return 0; }
G.Bretschneider公式
#include<bits/stdc++.h> using namespace std; int a,b,c,d; int main() { ios::sync_with_stdio(false); int T,z = 0; cin >> T; while(T--) { cin >> a >> b >> c >> d; if(a+b+c <= d || a+c+d <= b || a+b+d <= c || b+c+d <= a) { cout << "Case " << ++z << ": -1" << endl; continue; } double t = (double)(a+b+c+d)/2; double ans = sqrt((t-a)*(t-b)*(t-c)*(t-d)); cout << "Case " << ++z << ": " << fixed << setprecision(6) << ans << endl; } return 0; }
H.找规律打个表。
#include<bits/stdc++.h> using namespace std; long long n,a[50000]; int main() { ios::sync_with_stdio(false); for(int i = 1;i <= 50000;i++) a[i] = (long long)i*(i-1); int T; cin >> T; while(T--) { cin >> n; int t = lower_bound(a+1,a+50000,n)-a-1; long long ans1 = (long long)t*t+n-a[t]; long long ans2 = 0,now = 1; while(now*now < ans1) ans2 += (now*now-(now-1)*(now-1))*(now-1),now++; ans2 += (ans1-(now-1)*(now-1)+1)*(now-1); cout << ans1 << " " << ans2 << endl; } return 0; }
I.直接模拟加法。
#include<bits/stdc++.h> using namespace std; string s; int a[100005]; int main() { ios::sync_with_stdio(false); int T; cin >> T; while(T--) { memset(a,0,sizeof(a)); cin >> s; int sum = 0,cnt = 0; for(int i = s.length()-1;i >= 0;i--) { a[++cnt] = s[i]-'0'; sum += a[cnt]; } sum %= 10; do { if(a[1] != 9) { a[1]++; sum = (sum+1)%10; } else { int t = 1; a[1] = 0; sum = 0; for(int i = 2;i <= cnt;i++) { if(t) { a[i]++; if(a[i] == 10) a[i] = 0; else t = 0; } sum += a[i]; } if(t) { a[++cnt] = 1; sum++; } sum %= 10; } }while(sum != 0); int t = 100004; while(a[t] == 0) t--; while(t >= 1) { cout << a[t]; t--; } cout << endl; } return 0; }
J.把所有U替换成I,打表所有可能的个数。
#include<bits/stdc++.h> using namespace std; int n,ok[3000008]; string s; int main() { ios::sync_with_stdio(false); int now = 1; while(now <= 3000000) { ok[now] = 1; now *= 2; } for(int i = 3000000;i >= 1;i--) { if(ok[i+6]) ok[i] = 1; } int T; cin >> T; while(T--) { cin >> s; int flag = 0,sum = 0; if(s[0] != 'M') flag = 1; for(int i = 1;i < s.length();i++) { if(s[i] == 'M') flag = 1; else if(s[i] == 'U') sum += 3; else sum++; } if(flag == 0 && ok[sum]) cout << "Yes" << endl; else cout << "No" << endl; } return 0; }