2018-2019 ICPC, NEERC, Southern Subregional Contest (Online Mirror, ACM-ICPC Rules, Teams Preferred)
http://codeforces.com/contest/1070
A
给你一个d和s,求一个最小的数,使的能整除d,并且每位数的和为s。
如果确定了某n位数取模d的值,那么再计算同样的n位数,取模d也是相同的值时,就多此一举了。比如10%2 == 0 20%2 == 0 同样是两位数,取模2都是等于0。所以取最小的就可以了。
1 #include <bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const int N = 1e3+10; 5 struct Nod{ 6 int d, s; 7 string str; 8 }; 9 bool vis[N/2][N*5]; 10 int d, s; 11 void bfs() { 12 queue<Nod> que; 13 que.push({0,0,""}); 14 vis[0][0] = 1; 15 while(que.size()) { 16 Nod nod = que.front(); 17 que.pop(); 18 if(nod.s > s) continue; 19 if(nod.d == 0 && nod.s == s) { 20 cout << nod.str << endl; 21 return; 22 } 23 for(int i = 0; i < 10; i ++) { 24 int dd = (nod.d*10+i)%d; 25 int ss = nod.s + i; 26 if(!vis[dd][ss]) { 27 vis[dd][ss] = 1; 28 que.push({dd,ss,nod.str+char(i+'0')}); 29 } 30 } 31 } 32 cout << -1 << endl; 33 } 34 35 int main() { 36 cin >> d >> s; 37 bfs(); 38 return 0; 39 }
D
扔垃圾问题,当天的垃圾可以今天扔也可以明天扔,但最后一天的垃圾必须当天扔。每k个垃圾要用一个垃圾袋。求用垃圾袋最小的数量。
1 #include <bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const int N = 1e5+10; 5 6 int main() { 7 ll n, k; 8 cin >> n >> k; 9 ll ans = 0, x, pre = 0; 10 for(int i = 1; i <= n; i ++) { 11 cin >> x; 12 if(i == n) { 13 ans += (x+pre+k-1)/k; 14 break; 15 } 16 if(pre > 0) { 17 ans ++; 18 x = max(0LL,x - (k-pre)); 19 } 20 ans += x/k; 21 pre = x-x/k*k; 22 } 23 printf("%lld\n",ans); 24 return 0; 25 }
F
有n个观众,每个人有两个由'0'和'1'组成的字符串,还有一个值。从中选取一些观众,使的第一个1的数量和第二个1的数量都不小于一半。
贪心问题,两个1的全部都选上,然后再选取写与01和10组成的,按价值最大的取,最后在去00或01或10 数量不超过11的数量就行。
1 #include <bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const int N = 4e5+10; 5 int a[N], b[N], c[N], d[N]; 6 bool cmp(int x, int y) { 7 return x > y; 8 } 9 int main() { 10 int n, x; 11 cin >> n; 12 string s; 13 for(int i = 1; i <= n; i ++) { 14 cin >> s >> x; 15 if(s == "11") a[++a[0]] = x; 16 else if(s == "10") b[++b[0]] = x; 17 else if(s == "01") c[++c[0]] = x; 18 else d[++d[0]] = x; 19 } 20 sort(a+1,a+1+a[0],cmp); 21 sort(b+1,b+1+b[0],cmp); 22 sort(c+1,c+1+c[0],cmp); 23 ll ans = 0; 24 for(int i = 1; i <= a[0]; i ++) ans += 1LL*a[i]; 25 for(int i = 1; i <= min(b[0],c[0]); i ++) ans += 1LL*(b[i]+c[i]); 26 for(int i = min(b[0],c[0])+1; i <= max(b[0],c[0]); i ++) d[++d[0]] = max(b[i],c[i]); 27 sort(d+1,d+1+d[0],cmp); 28 for(int i = 1; i <= min(a[0],d[0]); i ++) ans += 1LL*d[i]; 29 printf("%lld\n",ans); 30 return 0; 31 }
H
有n个字符串和q个询问,每次询问有一个字符串s,问这个字符串s是n个字符串中的多少个的子串。
由于n个字符串最多8个字符,它的子串数量最多32个。就预处理一下很好就算出来了。
1 #include <bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const int N = 1e4+10; 5 map<string,int> mp1, mp2; 6 set<string> st; 7 string s[N]; 8 int main() { 9 ios::sync_with_stdio(false); 10 cin.tie(0); 11 cout.tie(0); 12 int n, q; 13 cin >> n; 14 string ss; 15 for(int i = 1; i <= n; i ++) { 16 cin >> s[i]; 17 st.clear(); 18 int len = s[i].length(); 19 for(int j = 0; j < len; j ++) { 20 for(int k = 1; k <= len-j; k ++) { 21 ss = s[i].substr(j,k); 22 st.insert(ss); 23 } 24 } 25 for(auto tmp : st) { 26 mp1[tmp]++; 27 mp2[tmp] = i; 28 //cout << tmp << endl; 29 } 30 } 31 cin >> q; 32 while(q--) { 33 cin >> ss; 34 if(mp1.count(ss)) { 35 cout << mp1[ss] << ' ' << s[mp2[ss]] << endl;; 36 } else cout << "0 -\n"; 37 } 38 return 0; 39 }
k
有n个数,为是否可以分成k份,使的每一份的和都相同。
签到题。
1 #include <bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const int N = 1e5+10; 5 int a[N], n, k, sum = 0; 6 7 int find(int x) { 8 int l = 1, r = n; 9 while(l <= r) { 10 int m = (l +r)>>1; 11 if(a[m] == x) return m; 12 if(a[m] < x) l = m+1; 13 else r = m - 1; 14 } 15 return -1; 16 } 17 18 int main() { 19 cin >> n >> k; 20 for(int i = 1; i <= n; i ++) { 21 cin >> a[i]; 22 a[i] += a[i-1]; 23 } 24 if(a[n]%k != 0) return 0*printf("No\n"); 25 int num = a[n]/k; 26 vector<int> v; 27 for(int i = 1; i <= k; i ++) { 28 int id = find(i*num); 29 if(id == -1) return 0*printf("No\n"); 30 v.push_back(id); 31 } 32 printf("Yes\n%d",v[0]); 33 for(int i = 1; i < v.size(); i ++) { 34 printf(" %d",v[i]-v[i-1]); 35 } 36 return 0; 37 }