2020大一个人赛(10)题解 2018-2019 ACM-ICPC Pacific Northwest Regional Contest (Div. 1)

2018-2019 ACM-ICPC Pacific Northwest Regional Contest (Div. 1)部分题

A - Exam

题意:给你k(朋友正确个数)和两个字符串(你和你朋友的答案),问你能答对的最大个数

思路:找你和朋友相同的个数,然后进行判断就行。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<vector>
 4 #include<map>
 5 #include<cstring>
 6 using namespace std;
 7 #define ll long long
 8 const int N = 2e6+25;
 9 const int mod = 1e9 + 7;
10 ll a[N];
11 int main()
12 {
13     ll n, ans = 0, sum = 0;
14     cin >> n;
15     string s1, s2;
16     cin >> s1 >> s2;
17     for (int i = 0; i < s1.size(); i++)
18     {
19         if (s1[i] == s2[i])
20             ans++;
21         else
22             sum++;
23     }
24     if (ans == n)
25         cout << s1.size() << endl;
26     else if (ans > n)
27         cout << n + sum << endl;
28     else cout << s1.size() - (n - ans) << endl;
29     
30    
31 
32 }

B - Coprime Integers

 题意:给你区间【a,b】【c,d】,问你互质整数对的数量。

思路:莫比乌斯反演算法,反演公式如下:(群里有模板OvO)

献上代码

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<vector>
 4 #include<map>
 5 #include<cstring>
 6 using namespace std;
 7 #define ll long long
 8 const int N = 1e7+2;
 9 const int mod = 1e9 + 7;
10 const int MAXN = 1e7+2;
11 bool check[MAXN + 10];
12 int prime[MAXN + 10];
13 int mu[MAXN + 10];
14 void Moblus()
15 {
16     memset(check, false, sizeof(check));
17     mu[1] = 1;
18     int tot = 0;
19     for (int i = 2; i <= MAXN; i++)
20     {
21         if (!check[i])
22         {
23             prime[tot++] = i;
24             mu[i] = -1;
25         }
26         for (int j = 0; j < tot; j++)
27         {
28             if (i * prime[j] > MAXN) break;
29             check[i * prime[j]] = true;
30             if (i % prime[j] == 0)
31             {
32                 mu[i * prime[j]] = 0;
33                 break;
34             }
35             else
36             {
37                 mu[i * prime[j]] = -mu[i];
38             }
39         }
40     }
41 }
42 int sum[MAXN + 10];
43 //找[1,n],[1,m]内互质的数的对数
44 long long solve(int n, int m)
45 {
46     long long ans = 0;
47     if (n > m)swap(n, m);
48     for (int i = 1, la = 0; i <= n; i = la + 1)
49     {
50         la = min(n / (n / i), m / (m / i));
51         ans += (long long)(sum[la] - sum[i - 1]) * (n / i) * (m / i);
52     }
53 
54     return ans;
55 }
56 int main()
57 {
58     Moblus();
59     sum[0] = 0;
60     for (int i = 1; i <= MAXN; i++)
61         sum[i] = sum[i - 1] + mu[i];
62     int a, b, c, d, k;
63     int T;
64     scanf("%d%d%d%d", &a, &b, &c, &d);
65    long long ans = solve(b, d) - solve((a - 1), d) - solve(b , (c - 1))
66           + solve((a - 1), (c - 1));
67         printf("%lld
", ans);
68     
69     return 0;
70 }

C - Contest Setting

题意:给你n个数和选取k种不同难度的题,问有多少方案。

思路:dp,dp[i][j]表示前i种选j个的方案数,先进行排序,算不同难度的个数存进数组,将其dp就是答案。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<vector>
 4 #include<map>
 5 #include<cstring>
 6 using namespace std;
 7 #define ll long long
 8 const int N = 1e3+5;
 9 const int mod = 998244353;
10 ll dp[N][N];
11 ll kind[N];
12 ll a[N];
13 int main()
14 {
15     ll i, j, k;
16     ll n,  t,count=0;
17     cin >> n >> k;
18     for (i = 1; i <= n; i++)
19     {
20         cin >> a[i];
21     }
22     sort(a + 1, a + n + 1);
23     ll cnt = 1, tot = 1;
24     for (int i = 2; i <= n; i++)//
25     {
26         if (a[i] == a[i - 1])
27         {
28             cnt++;
29         }
30         else
31         {
32             kind[tot++] = cnt;
33             cnt = 1;
34         }
35     }
36     kind[tot] = cnt;//算不同种的个数
37     memset(dp, 0, sizeof(dp));
38     for (int i = 0; i <= 1000; i++)
39     {
40         dp[i][0] = 1;
41     }
42     for (i = 1; i <= tot; i++)//选第i种难度
43     {
44         for (j = 1; j <= k; j++)//选1-k个
45         {
46             dp[i][j] = ((dp[i - 1][j - 1] * kind[i] % mod) + dp[i - 1][j]) % mod;
47         }
48     }
49     cout << dp[tot][k] << endl;
50     
51     
52 
53     
54 }

D - Count The Bits

 题意:给你整数k和b位数,问0-2^b-1被k整除的个数

思路:数位dp,

dp[i][j][0]表示前i位构成的数中对k取模为j的数的个数

dp[i][j][1]表示前i位构成的数中对k取模为j的数中二进制中1的个数

 所求结果就是dp[b][0][1],即b位数能被k整除后二进制1的个数

代码

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<vector>
 4 #include<map>
 5 #include<cstring>
 6 using namespace std;
 7 #define ll long long
 8 const int N = 1e3+5;
 9 const int mod = 1e9+9;
10 ll dp[129][N][2];
11 //dp[i][j][0]表示前i位构成的数中对k取模为j的数的个数
12 //dp[i][j][1]表示前i位构成的数中对k取模为j的数中二进制中1的个数
13 
14 int main()
15 {
16     ll i, j, k;
17     ll n,t,b;
18     cin >> k >> b;
19     dp[0][0][0] = 1;
20     dp[0][0][1] = 0;
21     for (i = 1; i <= b; i++)//前i位
22     {
23         for (j = 0; j < k; j++)
24         {
25             dp[i][j *2 % k][0] = (dp[i][(j *2) % k][0] + dp[i - 1][j][0]) % mod;
26             dp[i][(j*2 + 1) % k][0] = (dp[i][(j*2 + 1) % k][0] + dp[i - 1][j][0]) % mod;
27             
28             dp[i][(j * 2) % k][1] = (dp[i][(j * 2) % k][1] + dp[i - 1][j][1]) % mod;
29             dp[i][(j * 2 + 1) % k][1] = (dp[i][(j * 2 + 1) % k][1] + dp[i - 1][j][1] + dp[i - 1][j][0]) %mod;
30         }
31     }
32     cout << dp[b][0][1];
33   
34     
35     
36 
37     
38 }

E - Goat on a Rope

题意:给你山羊(x,y),和矩形中心对称两端点(x1,y1)(x2,y2),求绳子I不到矩形的最大长度

思路,点到矩形的最近距离

代码

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<vector>
 4 #include<map>
 5 #include<cstring>
 6 using namespace std;
 7 #define ll long long
 8 const int N = 1e3+5;
 9 const int mod = 1e9+9;
10 double cal(double x1, double y1, double x2, double y2)
11 {
12     return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
13 }
14 int main()
15 {
16     ll i, j, k;
17     ll n, t, b;
18     double ans = mod;
19     double x, y, x1, x2, y2, y1;
20     cin >> x >> y >> x1 >> y1 >> x2 >> y2;
21     if (x >= min(x1, x2) && x <= max(x2, x1)) //在x1和x2之间,距离为与y的距离
22         ans = min(abs(y1 - y), abs(y2 - y));
23     else if (y >= min(y1, y2) && y <= max(y1, y2))//在y1和y2之间,距离为与x的距离 
24         ans = min(abs(x - x1), abs(x - x2));
25     else 
26         ans = min(cal(x, y, x1, y1), min(cal(x, y, x2, y2), min(cal(x, y, x1, y2), cal(x, y, x2, y1))));//四端点的距离
27     printf("%.3f
", ans);
28     
29 }

F - Repeating Goldbachs

 题意:给你 一个数x(x≥4),将他拆分成两个质数,俩质数之差得到一个数再拆分,直至x<4,问多少步

思路:打表质数,然后暴力即可

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<vector>
 4 #include<map>
 5 #include<cstring>
 6 using namespace std;
 7 #define ll long long
 8 const int N = 1e6+5;
 9 const int mod = 1e9+9;
10 bool vis[N + 100];
11 ll prime[N + 100];
12 ll cnt = 0;
13 void dabiao()
14 {
15     vis[0] = vis[1] = 1;
16     for (int i = 2; i <= N; i++)
17     {
18         if (!vis[i])
19         {
20             prime[cnt++] = i;
21             for (int j = i + i; j <= N; j += i)
22                 vis[j] = 1;
23         }
24     }
25 }
26 int main()
27 {
28     ll i, j, k;
29     ll n, t, b;
30     dabiao();
31     cin >> n;
32     ll tmp = n,count=0;
33     while (tmp >= 4)
34     {
35         for (j = 0; j < cnt; j++)
36         {
37             k = tmp - prime[j];
38             if (vis[k] == 0)
39             {
40                 count++;
41                 tmp = abs(k - prime[j]);
42                 break;
43             }
44         }
45     }
46     cout << count << endl;
47 }

G - The Ending Point

题意:给你起点(x,y)和一个字符串(上下左右),问终点

思路:纯代入

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<vector>
 4 #include<map>
 5 #include<cstring>
 6 using namespace std;
 7 #define ll long long
 8 const int N = 2e6+25;
 9 const int mod = 1e9 + 7;
10 ll a[N];
11 int main()
12 {
13     ll i, j, k;
14     ll n, m, t;
15     ll x, y;
16     string s;
17     cin >> x >> y;
18     cin >> s;
19     for (i = 0; i < s.size(); i++)
20     {
21         if (s[i] == 'U')
22             y++;
23         else if (s[i] == 'D')
24             y--;
25         else if (s[i] == 'L')
26             x--;
27         else if (s[i] == 'R')
28             x++;
29     }
30     cout << x << " " << y;
31     
32    
33 
34 }

H - Weird Game

题意:给你n个蛋糕,有两个操作可以选择:吃一个,吃半个,Mahmoud先吃,Bashar后吃,蛋糕剩一个的时候对手输,两个人玩的很好。

思路:简单思路型的博弈论,当n为奇数时,达到权衡,Bashar跟着Mahmoud吃一样的量,达到胜利,相反n为偶数时,Mahmoud胜利。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<vector>
 4 #include<map>
 5 #include<cstring>
 6 using namespace std;
 7 #define ll long long
 8 const int N = 2e6+25;
 9 const int mod = 1e9 + 7;
10 ll a[N];
11 int main()
12 {
13     ll i, j, k;
14     ll n, m, t;
15     ll x, y;
16     cin >> n;
17     if(n%2==0)
18         puts("Mahmoud");
19     else
20         puts("Bashar");
21    
22    
23 
24 }

I - Time Limits

题意:给你n个t毫秒时间和s倍,求以整数秒限制所有的t。

思路:找最大的t,乘s倍,毫秒变整数秒向上取整(我直接+999省工作23333)

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<vector>
 4 #include<map>
 5 #include<cstring>
 6 using namespace std;
 7 #define ll long long
 8 const int N = 2e6+25;
 9 const int mod = 1e9 + 7;
10 ll a[N];
11 int main()
12 {
13     ll i, j, k;
14     ll n, m, t;
15     ll x, y,s;
16     cin >> n>>s;
17     for (i = 0; i < n; i++)
18         cin >> a[i];
19     sort(a, a + n);
20     cout << (a[n - 1] * s + 999) / 1000 << endl;
21    
22    
23 
24 }
原文地址:https://www.cnblogs.com/ch-hui/p/12780868.html