Codeforces Round #540 (Div. 3)题解
题目链接:
https://codeforces.com/contest/1118
A题:
题意:
q次查询,给你一个n,要你用1和2来凑出n,1的花费为a,2的花费为b,求花费的最小值。
思路:
我们知道当2*a<=b时全用1来肯定是最优的,当2*a>b时,若n为奇数就是1个1其他全是2,若n为偶数就全都是2这样是最优的。
代码实现如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <set> 2 #include <map> 3 #include <deque> 4 #include <queue> 5 #include <stack> 6 #include <cmath> 7 #include <ctime> 8 #include <bitset> 9 #include <cstdio> 10 #include <string> 11 #include <vector> 12 #include <cstdlib> 13 #include <cstring> 14 #include <iostream> 15 #include <algorithm> 16 using namespace std; 17 18 typedef long long LL; 19 typedef pair<LL, LL> pLL; 20 typedef pair<LL, int> pLi; 21 typedef pair<int, LL> pil;; 22 typedef pair<int, int> pii; 23 typedef unsigned long long uLL; 24 25 #define lson rt<<1 26 #define rson rt<<1|1 27 #define lowbit(x) x&(-x) 28 #define name2str(name) (#name) 29 #define bug printf("*********\n") 30 #define debug(x) cout<<#x"=["<<x<<"]" <<endl 31 #define FIN freopen("D://code//in.txt","r",stdin) 32 #define IO ios::sync_with_stdio(false),cin.tie(0) 33 34 const double eps = 1e-8; 35 const int mod = 1000000007; 36 const int maxn = 2e5 + 7; 37 const double pi = acos(-1); 38 const int inf = 0x3f3f3f3f; 39 const LL INF = 0x3f3f3f3f3f3f3f3fLL; 40 41 int q; 42 LL n, a, b; 43 44 int main(){ 45 scanf("%d", &q); 46 while(q--) { 47 scanf("%lld%lld%lld", &n, &a, &b); 48 LL ans = 0; 49 if(2 * a <= b) { 50 ans = n * a; 51 } else { 52 ans = n / 2 * b + (n % 2) * a; 53 } 54 printf("%lld\n", ans); 55 } 56 return 0; 57 }
B题:
题意:
给你n个数,要你去掉一个数,然后剩余的n-1个数保持相对顺序不变,问有多少种方案使得剩下的数中奇数项的和等于偶数项的和。
思路:
我们知道去掉一个数后对前面的数的位置的奇偶性不会产生影响,后面的数的位置的奇偶性变为对立的,因此我们只需要求下奇数项和偶数项的前缀和即可。
代码实现如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <set> 2 #include <map> 3 #include <deque> 4 #include <queue> 5 #include <stack> 6 #include <cmath> 7 #include <ctime> 8 #include <bitset> 9 #include <cstdio> 10 #include <string> 11 #include <vector> 12 #include <cstdlib> 13 #include <cstring> 14 #include <iostream> 15 #include <algorithm> 16 using namespace std; 17 18 typedef long long LL; 19 typedef pair<LL, LL> pLL; 20 typedef pair<LL, int> pLi; 21 typedef pair<int, LL> pil;; 22 typedef pair<int, int> pii; 23 typedef unsigned long long uLL; 24 25 #define lson rt<<1 26 #define rson rt<<1|1 27 #define lowbit(x) x&(-x) 28 #define name2str(name) (#name) 29 #define bug printf("*********\n") 30 #define debug(x) cout<<#x"=["<<x<<"]" <<endl 31 #define FIN freopen("D://code//in.txt","r",stdin) 32 #define IO ios::sync_with_stdio(false),cin.tie(0) 33 34 const double eps = 1e-8; 35 const int mod = 1000000007; 36 const int maxn = 2e5 + 7; 37 const double pi = acos(-1); 38 const int inf = 0x3f3f3f3f; 39 const LL INF = 0x3f3f3f3f3f3f3f3fLL; 40 41 int n; 42 LL a[maxn], sum1[maxn], sum2[maxn]; 43 44 int main(){ 45 scanf("%d", &n); 46 for(int i = 1; i <= n; i++) { 47 scanf("%lld", &a[i]); 48 sum1[i] = sum1[i-1]; 49 sum2[i] = sum2[i-1]; 50 if(i & 1) sum1[i] += a[i]; 51 else sum2[i] += a[i]; 52 } 53 int ans = 0; 54 for(int i = 1; i <= n; i++) { 55 if(sum1[i-1] + sum2[n] - sum2[i] == sum2[i-1] + sum1[n] - sum1[i]) { 56 ans++; 57 } 58 } 59 printf("%d\n", ans); 60 return 0; 61 }
C题:
题意:
给你n*n个数要你构建一个每行每列都是回文的矩阵。
思路:
模拟即可。
代码实现如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <set> 2 #include <map> 3 #include <deque> 4 #include <queue> 5 #include <stack> 6 #include <cmath> 7 #include <ctime> 8 #include <bitset> 9 #include <cstdio> 10 #include <string> 11 #include <vector> 12 #include <cstdlib> 13 #include <cstring> 14 #include <iostream> 15 #include <algorithm> 16 using namespace std; 17 18 typedef long long LL; 19 typedef pair<LL, LL> pLL; 20 typedef pair<LL, int> pLi; 21 typedef pair<int, LL> pil;; 22 typedef pair<int, int> pii; 23 typedef unsigned long long uLL; 24 25 #define lson rt<<1 26 #define rson rt<<1|1 27 #define lowbit(x) x&(-x) 28 #define name2str(name) (#name) 29 #define bug printf("*********\n") 30 #define debug(x) cout<<#x"=["<<x<<"]" <<endl 31 #define FIN freopen("D://code//in.txt","r",stdin) 32 #define IO ios::sync_with_stdio(false),cin.tie(0) 33 34 const double eps = 1e-8; 35 const int mod = 1000000007; 36 const int maxn = 2e5 + 7; 37 const double pi = acos(-1); 38 const int inf = 0x3f3f3f3f; 39 const LL INF = 0x3f3f3f3f3f3f3f3fLL; 40 41 int n, x; 42 int mp[25][25], cnt[1007]; 43 44 int main(){ 45 scanf("%d", &n); 46 for(int i = 1; i <= n * n; i++) { 47 scanf("%d", &x); 48 cnt[x]++; 49 } 50 if(n % 2 == 0) { 51 for(int i = 1; i <= 1000; i++) { 52 if(cnt[i] % 4 != 0) { 53 return printf("NO\n") * 0; 54 } 55 } 56 int pp = 1; 57 for(int i = 1; i <= n / 2; i++) { 58 for(int j = 1; j <= n / 2; j++) { 59 while(cnt[pp] == 0) pp++; 60 mp[i][j] = mp[i][n-j+1] = mp[n-i+1][j] = mp[n-i+1][n-j+1] = pp; 61 cnt[pp] -= 4; 62 } 63 } 64 } else { 65 int num1 = 0, num2 = 0, num3 = 0; 66 for(int i = 1; i <= 1000; i++) { 67 if(cnt[i] % 4 == 1) num1++; 68 else if(cnt[i] % 4 == 2) num2++; 69 else if(cnt[i] % 4 == 3) num3++; 70 } 71 if(num2 > (n-1) || (num1 > 0 && num3 > 0) || (num1 == 0 && num3 != 1) || (num3 == 0 && num1 != 1)) return printf("NO\n") * 0; 72 for(int i = 1; i <= 1000; i++) { 73 if(cnt[i] % 4 == 1 || cnt[i] % 4 == 3) { 74 mp[n/2+1][n/2+1] = i; 75 cnt[i]--; 76 break; 77 } 78 } 79 int pp = 1; 80 for(int i = 1; i <= n / 2; i++) { 81 for(int j = 1; j <= n / 2; j++) { 82 while(cnt[pp] < 4) pp++; 83 mp[i][j] = mp[i][n-j+1] = mp[n-i+1][j] = mp[n-i+1][n-j+1] = pp; 84 cnt[pp] -= 4; 85 } 86 } 87 pp = 1; 88 for(int i = 1; i <= n / 2; i++) { 89 while(cnt[pp] == 0) { 90 pp++; 91 if(pp > 1000) return printf("NO\n") * 0; 92 } 93 mp[i][n/2+1] = mp[n-i+1][n/2+1] = pp; 94 cnt[pp] -= 2; 95 } 96 for(int i = 1; i <= n / 2; i++) { 97 while(cnt[pp] < 2) { 98 pp++; 99 if(pp > 1000) return printf("NO\n") * 0; 100 } 101 if(pp > 1000) return printf("NO\n") * 0; 102 mp[n/2+1][i] = mp[n/2+1][n-i+1] = pp; 103 cnt[pp] -= 2; 104 } 105 } 106 printf("YES\n"); 107 for(int i = 1; i <= n; i++) { 108 for(int j = 1; j <= n; j++) { 109 printf("%d ", mp[i][j]); 110 } 111 printf("\n"); 112 } 113 return 0; 114 }
D题:
题意:
有n杯咖啡,m页作业,每杯咖啡的权值为ai,假如你某一天喝了k杯咖啡那么你写的作业页数为a1,a2-1,a3-2……这里的1,2,3指当天喝的顺序而非原序列的下标,要你用最少的天数写完作业。
思路:
先将ai从大到小排序,二分天数,然后把所有会产生正贡献的咖啡求和,与m比较即可。
代码实现如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <set> 2 #include <map> 3 #include <deque> 4 #include <queue> 5 #include <stack> 6 #include <cmath> 7 #include <ctime> 8 #include <bitset> 9 #include <cstdio> 10 #include <string> 11 #include <vector> 12 #include <cstdlib> 13 #include <cstring> 14 #include <iostream> 15 #include <algorithm> 16 using namespace std; 17 18 typedef long long LL; 19 typedef pair<LL, LL> pLL; 20 typedef pair<LL, int> pLi; 21 typedef pair<int, LL> pil;; 22 typedef pair<int, int> pii; 23 typedef unsigned long long uLL; 24 25 #define lson rt<<1 26 #define rson rt<<1|1 27 #define lowbit(x) x&(-x) 28 #define name2str(name) (#name) 29 #define bug printf("*********\n") 30 #define debug(x) cout<<#x"=["<<x<<"]" <<endl 31 #define FIN freopen("D://code//in.txt","r",stdin) 32 #define IO ios::sync_with_stdio(false),cin.tie(0) 33 34 const double eps = 1e-8; 35 const int mod = 1000000007; 36 const int maxn = 2e5 + 7; 37 const double pi = acos(-1); 38 const int inf = 0x3f3f3f3f; 39 const LL INF = 0x3f3f3f3f3f3f3f3fLL; 40 41 int n, m; 42 int a[maxn]; 43 44 bool check(int x) { 45 int tmp = 0; 46 LL sum = 0; 47 for(int i = 1; i <= min(n, x); i++) { 48 sum += a[i]; 49 } 50 for(int i = x + 1; i <= n; i++) { 51 if(i % x == 1 || x == 1) tmp++; 52 if(a[i] - tmp > 0) { 53 sum += a[i] - tmp; 54 } else { 55 break; 56 } 57 } 58 return sum >= m; 59 } 60 61 bool cmp(int a, int b) { 62 return a > b; 63 } 64 65 int main(){ 66 scanf("%d%d", &n, &m); 67 LL sum = 0; 68 for(int i = 1; i <= n; i++) { 69 scanf("%d", &a[i]); 70 sum += a[i]; 71 } 72 sort(a + 1, a + n + 1, cmp); 73 if(sum < m) { 74 return printf("-1\n") * 0; 75 } 76 int ub = inf, lb = 1, mid, ans = 0; 77 while(ub >= lb) { 78 mid = (ub + lb) >> 1; 79 if(check(mid)) { 80 ub = mid - 1; 81 ans = mid; 82 } else { 83 lb = mid + 1; 84 } 85 } 86 printf("%d\n", ans); 87 return 0; 88 }
E题:
题意:
给你n和k,要你构建n对数,假设第i对为ai,bi,第j对为aj,bj,需满足一下条件:
- ai!=bi;
- ai==aj与bi==bj不能同时成立;
- 若j==i+1时,ai!=aj且bi!=bj。
思路:
第一个数一直是1~k的循环,第二个数则是2~k~1,3~k~2,4~k~2这样循环,我们知道满足题意的总排列对数只有k*(k-1)种(第一位放置方法有k种选择,第二位也有k种,故总的排列方法是k*k,其中只有1-1,2-2这种是不满足要求的),因此当n>k*(k-1)时输出NO。
代码实现如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,k; 4 pair<int,int> ans[200007]; 5 int main(){ 6 scanf("%d%d",&n,&k); 7 if(n>1LL*k*(k-1)) return puts("NO")*0; 8 int a=2,x=1,y=2; 9 for(int i = 1; i<=n;i++){ 10 ans[i]={x,y}; 11 x++,y++; 12 if(x>k) x = 1; 13 if(y>k) y =1; 14 if(y==a) { 15 a++; 16 if(a>k) a=1; 17 y = a; 18 } 19 } 20 puts("YES"); 21 for(int i =1;i<=n;i++){ 22 printf("%d %d\n",ans[i].first,ans[i].second); 23 } 24 return 0; 25 }
F1题:
题意:
给你一棵树,每个结点的颜色可以是0,1,2,要你删除一条边使得得到的两个联通块内不能同时出现1和2。
思路:
dfs记一下子树中的1和2的个数与总的1和2的个数比较即可。
代码实现如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <set> 2 #include <map> 3 #include <deque> 4 #include <queue> 5 #include <stack> 6 #include <cmath> 7 #include <ctime> 8 #include <bitset> 9 #include <cstdio> 10 #include <string> 11 #include <vector> 12 #include <cstdlib> 13 #include <cstring> 14 #include <iostream> 15 #include <algorithm> 16 using namespace std; 17 18 typedef long long LL; 19 typedef pair<LL, LL> pLL; 20 typedef pair<LL, int> pLi; 21 typedef pair<int, LL> pil;; 22 typedef pair<int, int> pii; 23 typedef unsigned long long uLL; 24 25 #define lson rt<<1 26 #define rson rt<<1|1 27 #define lowbit(x) x&(-x) 28 #define name2str(name) (#name) 29 #define bug printf("*********\n") 30 #define debug(x) cout<<#x"=["<<x<<"]" <<endl 31 #define FIN freopen("D://code//in.txt","r",stdin) 32 #define IO ios::sync_with_stdio(false),cin.tie(0) 33 34 const double eps = 1e-8; 35 const int mod = 1000000007; 36 const int maxn = 3e5 + 7; 37 const double pi = acos(-1); 38 const int inf = 0x3f3f3f3f; 39 const LL INF = 0x3f3f3f3f3f3f3f3fLL; 40 41 int n, u, v, num1, num2; 42 LL ans = 0; 43 int a[maxn], sum1[maxn], sum2[maxn]; 44 vector<int> G[maxn]; 45 46 void dfs(int u, int p) { 47 if(a[u] == 1) sum1[u]++; 48 else if(a[u] == 2) sum2[u]++; 49 for(int i = 0; i < (int)G[u].size(); i++) { 50 int v = G[u][i]; 51 if(v == p) continue; 52 dfs(v, u); 53 if((sum1[v] == num1 && sum2[v] == 0) || (sum2[v] == num2 && sum1[v] == 0)) ans++; 54 sum1[u] += sum1[v], sum2[u] += sum2[v]; 55 } 56 } 57 58 int main(){ 59 scanf("%d", &n); 60 for(int i = 1; i <= n; i++) { 61 scanf("%d", &a[i]); 62 if(a[i] == 1) num1++; 63 else if(a[i] == 2) num2++; 64 } 65 for(int i = 1; i < n; i++) { 66 scanf("%d%d", &u, &v); 67 G[u].push_back(v); 68 G[v].push_back(u); 69 } 70 dfs(1, 0); 71 printf("%lld\n", ans); 72 return 0; 73 }