Codeforces Round #837 (Div. 2)(A-C)

169 阅读5分钟

比赛链接:

Codeforces Round #837 (Div. 2)

A. Hossam and Combinatorics

codeforces.com/contest/177…

题目描述

t组数据,每组数据有n个数,问有多少数对的极差的绝对值等于这n个数中最大的极差的绝对值。

例如

 6
 7 2 8 3 2 10
 极差为10
 答案为4
 有(2, 10), (2, 10), (10, 2), (10, 2)四个数对(2为上面两个下标不同的2

思路

有两种情况,一种情况为所有数全部相等吗,即极差为0。另一种是存在不同的最小数和最大数,即极差不为0。

极差为0的情况,n个数中的任意一个数都可以和剩下的n-1个数配对,答案为n*(n-1)

极差不为0的情况,任意一个最小数都可以和所有最大数匹配,任意一个最大数也可以和所有的最小数匹配,答案为2 * mp[min(a[i])] * mp[max(a[i])]

代码

 #include <bits/stdc++.h>
 ​
 #define up(i, j, n, k) for (int i = j; i <= n; i += k)
 #define dw(i, j, n, k) for (int i = j; i >= n; i -= k)
 #define LL long long
 ​
 using namespace std;
 ​
 const int mod = 1e9 + 7;
 const int mn = 2e5 + 10;
 const int INF = 0x3f3f3f3f;
 const double eps = 1e-8;
 typedef pair<int, int> PII;
 ​
 int t;
 ​
 void solve() {
     LL n, mi = INF, mx = -INF;
     cin >> n;
     vector<LL> a(n + 1);
     map<LL, LL> mp;
     up(i, 1, n, 1) {
         cin >> a[i];
         mp[a[i]]++;
         mi = min(mi, a[i]);
         mx = max(mx, a[i]);
     }
     if (mi == mx) {
         cout << n * (n - 1) << "\n";
         return ;
     }
     cout << 2 * mp[mi] * mp[mx] << "\n";
 }
 ​
 int main() {
     // ios ::sync_with_stdio(false);
     // t = 1;
     cin >> t;
     while (t--) solve();
 }

B. Hossam and Friends

codeforces.com/contest/177…

题目描述

定义满足[i, i+1, i+2…j](1 \le i \le j \le n)为好区间,总共有1~n个数,有m对数不可以同时出现,问共计有多少好区间

例如

 4 2 (n和m)
 1 2
 2 3
 ​
 有1,2,3,4个数
 1,2不可以同时出现
 2,3不可以同时出现
 那么满足好区间的区间有[1],[2],[3],[4],[3,4];
 [1,2],[1,2,3],[1,2,3,4],[2,3],[2,3,4]都因为1,2或者2,3同时出现而不满足

思路

如果1,2 不能同时出现,那么1,3和1,4直到1,n都不能同时出现,所以在所有不可以同时出现的数对(x,y)中,对于所有x相同的数对,只需要记录最小的y即可。

当n=10时,如果(3, 5)不可以同时出现,那么1到5,1到6…都不可以出现,所以还需要预处理下如果第i个数可以到达的右端点远于i+1, i+2 ... n中任意一个数可以到达的右端点,那么将这第i个数可以到达的右端点更新为 i+1, i+2 ... n中可到达的右端点最小的点。我们可以从后向前更新,这样可以做到O(n)的更新。f[i] = min(f[i],f[i+1]) [i从n-1到1]

现在我们得到了所有可行的区间,那么如何不重复计算这些区间所有的子区间的数量呢?

如果采用\frac{n*(n-1)}{2}这个公式的话会计算出很多重复的区间,我们可以换个思路想,对于每个左端点只加上这个左端点可达的所有区间,例如区间[1,3]。可达的区间为[1],[1,2],[1,2,3],由于左端点的不同,可以保证不会有重复。ans += f[i] - i + 1 (f[i]存储的是i可达的右端点)

由于读入的右端点是不可达的,所有存储的时候右端点-1才是可以最远可以到达的点。

代码

 #include <bits/stdc++.h>
 #define up(i, j, n, k) for (int i = j; i <= n; i += k)
 #define dw(i, j, n, k) for (int i = j; i >= n; i -= k)
 #define LL long long
 #define midlr (l + r) >> 1
 #define rson k << 1 | 1
 #define lson k << 1
 ​
 using namespace std;
 ​
 typedef pair<int, int> PII;
 const int mod = 998244353;
 const int mn = 2e6 + 10;
 const int INF = 0x3f3f3f3f;
 ​
 LL n, m, a[mn], f[mn];
 ​
 void solve() {
     cin >> n >> m;
     up(i, 1, n, 1) f[i] = n;
     LL ans = 0;
     up(i, 1, m, 1) {
         LL x, y;
         cin >> x >> y;
         if (x > y) swap(x, y);
         f[x] = min(f[x], y - 1);
     }
 ​
     dw(i, n - 1, 1, 1) 
         if (f[i] > f[i + 1]) 
             f[i] = f[i + 1];
 ​
     up(i, 1, n, 1) 
         ans += f[i] - i + 1;
     cout << ans << "\n";
 }
 ​
 int main() {
     int t;
     ios ::sync_with_stdio(false);
     cin >> t;
     while (t--) {
         solve();
     }
     return 0;
 }
 ​

C. Hossam and Trainees

codeforces.com/contest/177…

题目描述

n个数,问存不存在两个数是不互质的。数的范围1 \le a_i \le 10^9

例如

 2 (t)
 3 (n)
 32 48 7 (n个数)
 3
 14 5 9
 ​
 YES 3248不互质
 NO 所有数都是互质的

思路

质因数分解板子题,由于10^9最大的因数也不会超过\sqrt{10^9},所以用欧拉筛绰绰有余。

对于每个a_i,我们都对其进行质因数分解,如果分解质因数后发现该因子再之前已经出现过mp[p[i]] != 0那么说明这个数与之前的某个数有共同的因子,所以直接输出yes即可

同时不要忘记存储质因数分解后剩下的x,如果x>1说明x本身也是个质数,需要存储起来

例如10000007和20000014,不存储x的话就会WA

代码

 #include <bits/stdc++.h>
 #define up(i, j, n, k) for (int i = j; i <= n; i += k)
 #define dw(i, j, n, k) for (int i = j; i >= n; i -= k)
 #define LL long long
 #define midlr (l + r) >> 1
 #define rson k << 1 | 1
 #define lson k << 1
 ​
 using namespace std;
 ​
 typedef pair<int, int> PII;
 const int mod = 998244353;
 const int mn = 2e6 + 10;
 const int INF = 0x3f3f3f3f;
 ​
 LL n, m, a[mn];
 ​
 LL p[mn], cnt;
 bool v[mn];
 bool judge_prime(int n) {
     if (n == 1) return false;
     if (n == 2 || n == 3) return true;
     if ((n % 6 != 5) && (n % 6 != 1)) return false;
     for (int i = 5; i <= n / i; i += 6)
         if ((n % i == 0) || (n % (i + 2) == 0)) return false;
     return true;
 }
 ​
 void solve() {
     cin >> n;
     map<LL, LL> mp, zz;
     int one = 0;
     up(j, 1, n, 1) cin >> a[j];
     up(j, 1, n, 1) {
         LL x = a[j];
         for (int i = 1; i <= cnt; i++) {
             if (p[i] * p[i] > x) break;
             if (x % p[i] == 0) {
                 if (mp[p[i]]) {
                     cout << "Yes\n";
                     return;
                 }
                 while (x % p[i] == 0) 
                     x /= p[i];
                 mp[p[i]] = 1;
             }
         }
         if (x > 1) {
             if (mp[x]) {
                 cout << "Yes\n";
                 return;
             }
             mp[x] = 1;
         }
     }
     cout << "No\n";
 }
 ​
 int main() {
     int t;
     ios ::sync_with_stdio(false);
     is_prime(100000);
     cin >> t;
     while (t--) {
         solve();
     }
     return 0;
 }
 ​