2019年湖南多校第一场||2018-2019 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2018)
第一场多校就打的这么惨,只能说自己太菜了,还需继续努力啊~
题目链接:
GYM链接:https://codeforces.com/gym/101933
CSU链接:http://acm.csu.edu.cn:20080/csuoj/contest/problemset?cid=2178
A题:
题意:
有n只青蛙掉到了井里,然后可以靠叠罗汉和向上跳逃离水井,每只青蛙有三个属性分别为跳高值,体重(承重能力),身高,问最多能有多少只青蛙能够逃离水井。
思路:
因为每只青蛙的承重能力是有限的,因此我们按照承重能力从大到小排序,然后进行背包,dp[i]表示体重为i最多能达到多高,转移方程为dp[i]=max(dp[i], dp[i+w]+h)。
代码实现如下:
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 #include <bits/stdc++.h> 17 using namespace std; 18 19 typedef long long LL; 20 typedef pair<LL, LL> pLL; 21 typedef pair<LL, int> pLi; 22 typedef pair<int, LL> piL;; 23 typedef pair<int, int> pii; 24 typedef unsigned long long uLL; 25 26 #define lson rt<<1 27 #define rson rt<<1|1 28 #define lowbit(x) x&(-x) 29 #define name2str(name) (#name) 30 #define bug printf("*********\n") 31 #define debug(x) cout<<#x"=["<<x<<"]" <<endl 32 #define FIN freopen("in","r",stdin) 33 #define IO ios::sync_with_stdio(false),cin.tie(0) 34 35 const double eps = 1e-8; 36 const int mod = 1e9 + 7; 37 const int maxn = 1e5 + 7; 38 const double pi = acos(-1); 39 const int inf = 0x3f3f3f3f; 40 const LL INF = 0x3f3f3f3f3f3f3f3fLL; 41 42 int n, d; 43 int dp[100000007]; 44 45 struct node { 46 int l, w, h; 47 bool operator < (const node& x) const { 48 return w > x.w; 49 } 50 }pp[maxn]; 51 52 int main() { 53 scanf("%d%d", &n, &d); 54 for(int i = 1; i <= n; ++i) { 55 scanf("%d%d%d", &pp[i].l, &pp[i].w, &pp[i].h); 56 } 57 sort(pp + 1, pp + n + 1); 58 int ans = 0; 59 for(int i = 1; i <= n; ++i) { 60 int w = pp[i].w; 61 for(int j = 1; j < w && (j + w) <= 1e8; ++j) { 62 dp[j] = min(d + 2, max(dp[j], dp[j+w] + pp[i].h)); 63 } 64 if(dp[w] + pp[i].l > d) ++ans; 65 } 66 printf("%d\n", ans); 67 return 0; 68 }
B题:
题意:
给你n个数字或者字符串,问你是否能够把它还原成1~n。
思路:
直接On遍历即可。
代码实现如下:
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 #include <bits/stdc++.h> 17 using namespace std; 18 19 typedef long long LL; 20 typedef pair<LL, LL> pLL; 21 typedef pair<LL, int> pLi; 22 typedef pair<int, LL> piL;; 23 typedef pair<int, int> pii; 24 typedef unsigned long long uLL; 25 26 #define lson rt<<1 27 #define rson rt<<1|1 28 #define lowbit(x) x&(-x) 29 #define name2str(name) (#name) 30 #define bug printf("*********\n") 31 #define debug(x) cout<<#x"=["<<x<<"]" <<endl 32 #define FIN freopen("in","r",stdin) 33 #define IO ios::sync_with_stdio(false),cin.tie(0) 34 35 const double eps = 1e-8; 36 const int mod = 1e9 + 7; 37 const int maxn = 1e6 + 7; 38 const double pi = acos(-1); 39 const int inf = 0x3f3f3f3f; 40 const LL INF = 0x3f3f3f3f3f3f3f3fLL; 41 42 int n; 43 char s[15]; 44 45 int main() { 46 int flag = 1; 47 scanf("%d", &n); 48 for(int i = 1; i <= n; i++) { 49 scanf("%s", s); 50 if(s[0] == 'm') continue; 51 int len = strlen(s); 52 int num = 0; 53 for(int j = 0; j < len; j++) { 54 num = num * 10 + s[j] - '0'; 55 } 56 if(num != i) flag = 0; 57 } 58 if(flag) puts("makes sense"); 59 else puts("something is fishy"); 60 return 0; 61 }
C题:
题意:
给定n天产生垃圾,第i天垃圾的累积量为,如果累积量在j+1天会大于等于20,则需在前一天打扫卫生,问至少需要打扫多少次卫生。
思路:
枚举天数,然后与前面没被清理的垃圾进行累计求和,如果大于等于20则将前面的垃圾清空。
代码实现如下:
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 #include <bits/stdc++.h> 17 using namespace std; 18 19 typedef long long LL; 20 typedef pair<LL, LL> pLL; 21 typedef pair<LL, int> pLi; 22 typedef pair<int, LL> piL;; 23 typedef pair<int, int> pii; 24 typedef unsigned long long uLL; 25 26 #define lson rt<<1 27 #define rson rt<<1|1 28 #define lowbit(x) x&(-x) 29 #define name2str(name) (#name) 30 #define bug printf("*********\n") 31 #define debug(x) cout<<#x"=["<<x<<"]" <<endl 32 #define FIN freopen("in","r",stdin) 33 #define IO ios::sync_with_stdio(false),cin.tie(0) 34 35 const double eps = 1e-8; 36 const int mod = 1e9 + 7; 37 const int maxn = 400 + 7; 38 const double pi = acos(-1); 39 const int inf = 0x3f3f3f3f; 40 const LL INF = 0x3f3f3f3f3f3f3f3fLL; 41 42 int n; 43 int a[maxn], vis[maxn]; 44 45 int main() { 46 scanf("%d", &n); 47 for(int i = 1; i <= n; i++) { 48 scanf("%d", &a[i]); 49 } 50 int ans = 0; 51 for(int i = 1; i <= 385; i++) { 52 int sum = 0; 53 for(int j = 1; j <= n; j++) { 54 if(a[j] > i) break; 55 if(vis[a[j]]) continue; 56 sum += i - a[j]; 57 if(sum >= 20) { 58 ans++; 59 sum = 0; 60 for(int k = 1; k < i; k++) vis[k] = 1; 61 break; 62 } 63 } 64 } 65 printf("%d\n", ans); 66 return 0; 67 }
D题:
题意:
有一家披萨店要配送披萨,给定一张有n个结点的图和m条有边权的边,有q份订单,每份订单给定下单时间,终点,制作这份披萨结束的时间,问你这q份订单中要等待的最长时间的最小值(注意一次可以配送多份订单,但需要按照下单时间来,下单时间和制作完成时间单调递增)。
思路:
因为一次可以拿多份披萨进行配送且必须按照顺序配送,因此我们先跑n遍dijstra求出任意两点间的最短路。
二分需要等待的最长时间的最小值x,然后check进行dp,dp[u]表示配送完u这份订单且回到起点(1)的最短时间,由于q不大,因此我们可以枚举分界点进行分段,总复杂度为O(nmlog(n)+35q2)。
代码实现如下:
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 #include <bits/stdc++.h> 17 using namespace std; 18 19 typedef long long LL; 20 typedef pair<LL, LL> pLL; 21 typedef pair<LL, int> pLi; 22 typedef pair<int, LL> piL;; 23 typedef pair<int, int> pii; 24 typedef unsigned long long uLL; 25 26 #define lson rt<<1 27 #define rson rt<<1|1 28 #define lowbit(x) x&(-x) 29 #define name2str(name) (#name) 30 #define bug printf("*********\n") 31 #define debug(x) cout<<#x"=["<<x<<"]" <<endl 32 #define FIN freopen("in","r",stdin) 33 #define IO ios::sync_with_stdio(false),cin.tie(0) 34 35 const double eps = 1e-8; 36 const int mod = 1e9 + 7; 37 const int maxn = 1e3 + 7; 38 const double pi = acos(-1); 39 const int inf = 0x3f3f3f3f; 40 const LL INF = 0x3f3f3f3f3f3f3f3fLL; 41 42 int n, m, q, tot, u, v, w; 43 int head[maxn], vis[maxn]; 44 LL dis[maxn][maxn], dp[maxn]; 45 46 struct edge { 47 int v, w, next; 48 }ed[maxn*10]; 49 50 struct node { 51 int s, t, u; 52 }num[maxn]; 53 54 void add(int u, int v, int w) { 55 ed[tot].v = v; 56 ed[tot].w = w; 57 ed[tot].next = head[u]; 58 head[u] = tot++; 59 } 60 61 void dij(int s) { 62 priority_queue<pLi, vector<pLi>, greater<pLi> > q; 63 for(int i = 1; i <= n; ++i) { 64 vis[i] = 0; 65 dis[s][i] = INF; 66 } 67 dis[s][s] = 0; 68 q.push({0, s}); 69 int u, v; 70 while(!q.empty()) { 71 u = q.top().second; q.pop(); 72 if(vis[u]) continue; 73 vis[u] = 1; 74 for(int i = head[u]; ~i; i = ed[i].next) { 75 v = ed[i].v; 76 if(dis[s][v] > dis[s][u] + ed[i].w) { 77 dis[s][v] = dis[s][u] + ed[i].w; 78 q.push({dis[s][v], v}); 79 } 80 } 81 } 82 } 83 84 bool check(LL x) { 85 for(int i = 1; i <= q; ++i) dp[i] = INF; 86 for(int i = 0; i < q; ++i) { 87 LL tmp = 0, las = dp[i], pp = INF; 88 for(int j = 1; i + j <= q; ++j) { 89 int v = i + j; 90 if(j == 1) tmp += dis[1][num[v].u]; 91 else tmp += dis[num[v-1].u][num[v].u]; 92 las = max(dp[i], 1LL * num[v].t); 93 if(las + tmp - num[v].s > x) break; 94 pp = min(pp, x + num[v].s - tmp); 95 if(pp < las) break; 96 dp[v] = min(dp[v], las + tmp + dis[num[v].u][1]); 97 } 98 } 99 return dp[q] < INF; 100 } 101 102 int main() { 103 scanf("%d%d", &n, &m); 104 for(int i = 1; i <= n; ++i) { 105 head[i] = -1; 106 } 107 for(int i = 1; i <= m; ++i) { 108 scanf("%d%d%d", &u, &v, &w); 109 add(u, v, w), add(v, u, w); 110 } 111 for(int i = 1; i <= n; ++i) dij(i); 112 scanf("%d", &q); 113 for(int i = 1; i <= q; ++i) { 114 scanf("%d%d%d", &num[i].s, &num[i].u, &num[i].t); 115 } 116 LL ub = 1e15, lb = 0, mid, ans = 0; 117 while(ub >= lb) { 118 mid = (ub + lb) >> 1; 119 if(check(mid)) { 120 ub = mid - 1; 121 ans = mid; 122 } else { 123 lb = mid + 1; 124 } 125 } 126 printf("%lld\n", ans); 127 return 0; 128 }
E题:
题意:
己方有n个小兵,敌方有m个小兵,每个小兵的血量给定,现在总共有d点伤害,d点伤害会一点一点地对场上所有活着的小兵中的某一个造成一点伤害(包括己方),每个小兵收到这点伤害的概率相等,问敌方小兵全死的概率。
思路:
有两种方法,一种是用十进制记录每个小兵现在还剩多少的血量,另一种是记录剩余血量为i的小兵有多少个,然后进行记忆化搜索,貌似第二种方法快一点。
代码实现如下:
第一种方法:
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 #include <bits/stdc++.h> 17 using namespace std; 18 19 typedef long long LL; 20 typedef pair<LL, LL> pLL; 21 typedef pair<LL, int> pLi; 22 typedef pair<int, LL> piL;; 23 typedef pair<int, int> pii; 24 typedef unsigned long long uLL; 25 26 #define lson rt<<1 27 #define rson rt<<1|1 28 #define lowbit(x) x&(-x) 29 #define name2str(name) (#name) 30 #define bug printf("*********\n") 31 #define debug(x) cout<<#x"=["<<x<<"]" <<endl 32 #define FIN freopen("in","r",stdin) 33 #define IO ios::sync_with_stdio(false),cin.tie(0) 34 35 const double eps = 1e-8; 36 const int mod = 1e9 + 7; 37 const int maxn = 1e6 + 7; 38 const double pi = acos(-1); 39 const int inf = 0x3f3f3f3f; 40 const LL INF = 0x3f3f3f3f3f3f3f3fLL; 41 42 int n, m, d, cnt, sum; 43 int a[15], b[15], c[15]; 44 LL pw[15]; 45 LL las; 46 unordered_map<LL, double> dp; 47 48 void update(LL& x) { 49 cnt = 0; 50 for(int i = n; i > 0; --i) a[i] = x % 10, x /= 10; 51 for(int i = m; i > 0; --i) b[i] = x % 10, x /= 10; 52 sort(a + 1, a + n + 1); 53 sort(b + 1, b + m + 1); 54 for(int i = 1; i <= m; ++i) x = x * 10 + b[i]; 55 for(int i = 1; i <= n; ++i) x = x * 10 + a[i]; 56 for(int i = 1; i <= n; ++i) { 57 c[n+1-i] = a[i]; 58 if(a[i] > 0) cnt++; 59 } 60 for(int i = 1; i <= m; ++i) { 61 c[n+m+1-i] = b[i]; 62 if(b[i] > 0) cnt++; 63 } 64 } 65 66 double dfs(LL nw, int d) { 67 update(nw); 68 int p[15]; 69 int num = cnt; 70 if(dp.find(nw) != dp.end()) return dp[nw]; 71 if(nw < las) return dp[nw] = 1.000000; 72 if(d == 0) return dp[nw] = 0.000000; 73 double tmp = 0; 74 for(int i = 1; i <= n + m; ++i) p[i] = c[i]; 75 for(int i = 1; i <= n + m; ++i) { 76 if(p[i] == 0) continue; 77 --p[i]; 78 if(p[i] == 0) num--; 79 tmp += dfs(nw - pw[i], d - 1) / (num + (p[i] == 0)); 80 if(p[i] == 0) num++; 81 ++p[i]; 82 } 83 return dp[nw] = tmp; 84 } 85 86 int main() { 87 scanf("%d%d%d", &n, &m, &d); 88 for(int i = 1; i <= n; ++i) scanf("%d", &a[i]), sum += a[i]; 89 for(int i = 1; i <= m; ++i) scanf("%d", &b[i]), sum += b[i]; 90 if(d >= sum) return printf("1.000000\n") * 0; 91 LL nw = 0; 92 las = 1; 93 cnt = n + m; 94 for(int i = 1; i <= m; ++i) nw = nw * 10 + b[i], c[n+m+1-i] = b[i]; 95 for(int i = 1; i <= n; ++i) nw = nw * 10 + a[i], las = las * 10, c[n+1-i] = a[i]; 96 pw[1] = 1; 97 for(int i = 2; i <= n + m; ++i) pw[i] = pw[i-1] * 10; 98 printf("%.7f\n", dfs(nw, d)); 99 return 0; 100 }
第二种方法:
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 #include <bits/stdc++.h> 17 using namespace std; 18 19 typedef long long LL; 20 typedef pair<LL, LL> pLL; 21 typedef pair<LL, int> pLi; 22 typedef pair<int, LL> piL;; 23 typedef pair<int, int> pii; 24 typedef unsigned long long uLL; 25 26 #define lson rt<<1 27 #define rson rt<<1|1 28 #define lowbit(x) x&(-x) 29 #define name2str(name) (#name) 30 #define bug printf("*********\n") 31 #define debug(x) cout<<#x"=["<<x<<"]" <<endl 32 #define FIN freopen("in","r",stdin) 33 #define IO ios::sync_with_stdio(false),cin.tie(0) 34 35 const double eps = 1e-8; 36 const int mod = 1e9 + 7; 37 const int maxn = 1e6 + 7; 38 const double pi = acos(-1); 39 const int inf = 0x3f3f3f3f; 40 const LL INF = 0x3f3f3f3f3f3f3f3fLL; 41 42 int n, m, d; 43 LL pw[15]; 44 unordered_map<LL, double> dp; 45 int a[7], b[7]; 46 47 double dfs(LL nw, int d) { 48 if(dp.find(nw) != dp.end()) return dp[nw]; 49 if(nw < pw[7]) return dp[nw] = 1.0; 50 if(d == 0) return dp[nw] = 0.0; 51 double tmp = 0; 52 int num = 0; 53 LL pp = nw; 54 for(int j = 1; j <= 12; ++j) { 55 num += pp % 10; 56 pp /= 10; 57 } 58 for(int i = 1; i <= 12; ++i) { 59 int x = (nw % pw[i+1]) / pw[i]; 60 if(x == 0) continue; 61 nw -= pw[i]; 62 if(i != 7 && i != 1) nw += pw[i-1]; 63 tmp += x * dfs(nw, d - 1) / num; 64 nw += pw[i]; 65 if(i != 7 && i != 1) nw -= pw[i-1]; 66 } 67 return dp[nw] = tmp; 68 } 69 70 int main() { 71 scanf("%d%d%d", &n, &m, &d); 72 int sum = 0; 73 for(int i = 1; i <= n; ++i) scanf("%d", &a[i]), sum += a[i]; 74 for(int i = 1; i <= m; ++i) scanf("%d", &b[i]), sum += b[i]; 75 if(sum <= d) return printf("1.0000000\n") * 0; 76 LL nw = 0; 77 pw[1] = 1; 78 for(int i = 2; i <= 13; ++i) pw[i] = pw[i-1] * 10; 79 for(int i = m; i >= 1; --i) nw += pw[6+b[i]]; 80 for(int i = n; i >= 1; --i) nw += pw[a[i]]; 81 printf("%.7f\n", dfs(nw, d)); 82 return 0; 83 }
H题:
题意:
你有一块边长为l的花园,然后有n个修理机器可以考虑,每个修理机器有名字、花费、工作速度、工作时间、充电时间,要你输出开销最小且能保证每周至少修理一次的所有机器的名字。
思路:
我们先按照花费从小到大排序然后计算是否能够保证每周至少修理一次即可。
代码实现如下:
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 #include <bits/stdc++.h> 17 using namespace std; 18 19 typedef long long LL; 20 typedef pair<LL, LL> pLL; 21 typedef pair<LL, int> pLi; 22 typedef pair<int, LL> piL;; 23 typedef pair<int, int> pii; 24 typedef unsigned long long uLL; 25 26 #define lson rt<<1 27 #define rson rt<<1|1 28 #define lowbit(x) x&(-x) 29 #define name2str(name) (#name) 30 #define bug printf("*********\n") 31 #define debug(x) cout<<#x"=["<<x<<"]" <<endl 32 #define FIN freopen("in","r",stdin) 33 #define IO ios::sync_with_stdio(false),cin.tie(0) 34 35 const double eps = 1e-8; 36 const int mod = 1e9 + 7; 37 const int maxn = 1e6 + 7; 38 const double pi = acos(-1); 39 const int inf = 0x3f3f3f3f; 40 const LL INF = 0x3f3f3f3f3f3f3f3fLL; 41 42 int l, m; 43 char s[155]; 44 45 struct node { 46 char name[65]; 47 int p, c, t, r, id; 48 bool operator < (const node& x) const { 49 return p == x.p ? id < x.id : p < x.p; 50 } 51 }num[105]; 52 53 int main() { 54 char* p; 55 scanf("%d%d", &l, &m); 56 getchar(); 57 for(int i = 1; i <= m; ++i) { 58 memset(s, '\0', sizeof(s)); 59 fgets(s, 150, stdin); 60 num[i].id = i; 61 p = strtok(s, ","); 62 int j = 0; 63 while(p) { 64 if(j == 0) strcpy(num[i].name, p); 65 else if(j == 1) num[i].p = atoi(p); 66 else if(j == 2) num[i].c = atoi(p); 67 else if(j == 3) num[i].t = atoi(p); 68 else num[i].r = atoi(p); 69 j++; 70 p = strtok(NULL, ","); 71 } 72 } 73 sort(num + 1, num + m + 1); 74 int mx = inf; 75 for(int i = 1; i <= m; ++i) { 76 if(10080.0 / (num[i].t + num[i].r) * num[i].c * num[i].t >= 1.0 * l) { 77 if(mx == inf || mx == num[i].p) { 78 printf("%s\n", num[i].name); 79 mx = num[i].p; 80 } 81 } 82 } 83 if(mx == inf) puts("no such mower"); 84 return 0; 85 }
I题:
题意:
题目我没读,不过大意差不多就是要你用这n个参赛人的权值凑出S,问恰好凑成S需要多少个人并输出他们的名字,权值按照从小到大排序保证前一个会小于等于当前数的一半。
思路:
因为题目保证第i小的数一定小于等于第i+1小的数的一半,因此我们可以得知将所有数按照从大到小排序然后能取的都取,最后看S是否会减为0,本题唯一难点就是需要大数,因此去学了一波java容器。
代码实现如下:
1 import java.math.*; 2 import java.util.*; 3 4 public class Main{ 5 public static void main(String[] args) { 6 Scanner sc = new Scanner(System.in); 7 int n; 8 BigInteger sum; 9 n = sc.nextInt(); 10 sum = sc.nextBigInteger(); 11 Map<BigInteger, String> mp = new HashMap<BigInteger, String>(); 12 Vector<BigInteger> v = new Vector<BigInteger>(); 13 String s; 14 BigInteger num; 15 for(int i = 1; i <= n; i++) { 16 s = sc.next(); 17 num = sc.nextBigInteger(); 18 mp.put(num, s); 19 v.add(num); 20 } 21 Collections.sort(v, Collections.reverseOrder()); 22 Vector<String> ans = new Vector<String>(); 23 for(int i = 0; i < n; i++) { 24 if(sum.compareTo(v.elementAt(i)) >= 0) { 25 ans.add(mp.get(v.elementAt(i))); 26 sum = sum.subtract(v.elementAt(i)); 27 } 28 } 29 if(sum.compareTo(BigInteger.valueOf(0)) != 0) { 30 ans.removeAllElements(); 31 } 32 System.out.println(ans.size()); 33 for(int i = 0; i < ans.size(); i++) { 34 System.out.println(ans.elementAt(i)); 35 } 36 sc.close(); 37 } 38 }
J题:
题意:
需要你构造一个01串,该01串需满足从其中任选两个字符保持原来的相对顺序,恰好有a种方法得到00,b种方法得到01,c种方法得到10,d种方法得到11。
思路:
因为是任选两个,因此我们可以通过组合数解出0的个数n和1的个数m(注意当a等于1时n等于2,d等于1时同理),当n*m!=b+c或者无法解除n或m时是无法构造的。
构造时我们发现讲1全部放左边0全部放右边,然后对于某一个0,每前移通过一个1都会多一个01,少一个10,通过比较b-num(num为当前已有01个数)与m比较知道这个0该放在哪里。
代码实现如下:
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 #include <bits/stdc++.h> 17 using namespace std; 18 19 typedef long long LL; 20 typedef pair<LL, LL> pLL; 21 typedef pair<LL, int> pLi; 22 typedef pair<int, LL> piL;; 23 typedef pair<int, int> pii; 24 typedef unsigned long long uLL; 25 26 #define lson rt<<1 27 #define rson rt<<1|1 28 #define lowbit(x) x&(-x) 29 #define name2str(name) (#name) 30 #define bug printf("*********\n") 31 #define debug(x) cout<<#x"=["<<x<<"]" <<endl 32 #define FIN freopen("in","r",stdin) 33 #define IO ios::sync_with_stdio(false),cin.tie(0) 34 35 const double eps = 1e-8; 36 const int mod = 1e9 + 7; 37 const int maxn = 1e6 + 7; 38 const double pi = acos(-1); 39 const int inf = 0x3f3f3f3f; 40 const LL INF = 0x3f3f3f3f3f3f3f3fLL; 41 42 LL a, b, c, d, n, m; 43 vector<int> v; 44 45 int main() { 46 scanf("%lld%lld%lld%lld", &a, &b, &c, &d); 47 if(a == 0 && b == 0 && c == 0 && d == 0) return printf("1\n") * 0; 48 if(a >= 2) { 49 n = (LL)sqrt(2 * a) + 1; 50 if(n * (n - 1) != 2 * a) return printf("impossible\n") * 0; 51 } else if(a == 1) n = 2; 52 else { 53 if(b != 0 || c != 0) n = 1; 54 } 55 if(d >= 2) { 56 m = (LL)sqrt(2 * d) + 1; 57 if(m * (m - 1) != 2 * d) return printf("impossible\n") * 0; 58 } else if(d == 1) m = 2; 59 else { 60 if(b != 0 || c != 0) m = 1; 61 } 62 if(n * m != b + c) return printf("impossible\n") * 0; 63 int num = 0; 64 while(num < b) { 65 if(b - num >= m) { 66 v.push_back(0); 67 n--; 68 num += m; 69 } else { 70 int cnt = 0; 71 for(int i = 0; i < m - (b - num); i++) { 72 v.push_back(1); 73 cnt++; 74 } 75 num = b; 76 m -= cnt; 77 v.push_back(0); 78 n--; 79 break; 80 } 81 } 82 while(m--) v.push_back(1); 83 while(n--) v.push_back(0); 84 for(auto x : v) { 85 printf("%d", x); 86 } 87 printf("\n"); 88 return 0; 89 }
K题:
题意:
给你n和k,表示有一棵有n个结点的树要你使用恰好k个颜色进行染色,求满足相邻结点颜色不相同的方案数。
思路:
我们定义f(x)为至多使用了x种颜色的方案数,易知当我们确定父亲结点的颜色后子结点的颜色只需要和父亲节点的颜色不同即可,因此除0号结点染色方案数为x外其他的都是x-1种方法,最后容斥一下即可。
代码实现如下:
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 #include <bits/stdc++.h> 17 using namespace std; 18 19 typedef long long LL; 20 typedef pair<LL, LL> pLL; 21 typedef pair<LL, int> pLi; 22 typedef pair<int, LL> piL;; 23 typedef pair<int, int> pii; 24 typedef unsigned long long uLL; 25 26 #define lson rt<<1 27 #define rson rt<<1|1 28 #define lowbit(x) x&(-x) 29 #define name2str(name) (#name) 30 #define bug printf("*********\n") 31 #define debug(x) cout<<#x"=["<<x<<"]" <<endl 32 #define FIN freopen("in","r",stdin) 33 #define IO ios::sync_with_stdio(false),cin.tie(0) 34 35 const double eps = 1e-8; 36 const int mod = 1e9 + 7; 37 const int maxn = 2500 + 7; 38 const double pi = acos(-1); 39 const int inf = 0x3f3f3f3f; 40 const LL INF = 0x3f3f3f3f3f3f3f3fLL; 41 42 int n, k; 43 LL A[maxn]; 44 45 LL qpow(LL x, int n) { 46 LL res = 1; 47 while(n) { 48 if(n & 1) res = res * x % mod; 49 x = x * x % mod; 50 n >>= 1; 51 } 52 return res; 53 } 54 55 LL get_num(int k) { 56 return 1LL * k * qpow(k - 1, n - 1) % mod; 57 } 58 59 LL C(int n, int m) { 60 return A[n] * qpow(A[m], mod - 2) % mod * qpow(A[n-m], mod - 2) % mod; 61 } 62 63 int main() { 64 scanf("%d%d", &n, &k); 65 A[0] = 1; 66 for(int i = 1; i <= k; i++) { 67 A[i] = A[i-1] * i % mod; 68 } 69 for(int i = 1; i < n; i++) { 70 scanf("%*d"); 71 } 72 int flag = 1; 73 LL ans = 0; 74 for(int i = k; i >= 1; i--) { 75 LL tmp = get_num(i) * C(k, i) % mod; 76 if(flag == 1) ans = (ans + tmp) % mod; 77 else ans = (ans - tmp + mod) % mod; 78 flag = -flag; 79 } 80 printf("%lld\n", ans); 81 return 0; 82 }