zoukankan      html  css  js  c++  java
  • HDU 5072 Coprime (乱搞?)

    题目链接 : http://acm.hdu.edu.cn/showproblem.php?pid=5072

    求n个不同的数(<=1e5)中有多少组三元组(a, b, c)两两不互质或者两两互质。

    做法:

    假定a < b < c

    (x, y, z)表示a和b之间的关系是X,a和c之间是Y,b和c之间关系是Z,X,Y,Z∈{0, 1}, 这里0代表不互质,1代表互质

    考虑到正的来做有点难,可以反的来做这题,总共(a,b,c)之间有8种关系

    我们可以求出其它6种,然后减一下就行了。

    先排序。

    A = {在b前与c互质的数量 * 在c前与c不互质的数量} + {在c后与c互质的数量 * 在c后与c不互质的数量};

    B = {在b前与b互质的数量 * 在b后与b互质的数量} + {在b前与b不互质的数量 * 在b后与b不互质的数量};

    Sum = 总共有多少组三元组;

    那么其实我们所求的答案就是(B - A + Sum) / 2 ; 这个建议自己推一下,也不是很复杂

    至于求在c前与c互质OR不互质的数量的话可以用容次搞搞,复杂度是可以过的。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <vector>
     5 
     6 using namespace std;
     7 typedef __int64 lld;
     8 const int MAXN = 100005;
     9 
    10 int a[MAXN];
    11 int cnt[MAXN];
    12 vector<int> prime[MAXN];
    13 int check[MAXN] = {0};
    14 int n;
    15 lld ans[MAXN][2];
    16 
    17 int calc(vector<int> arr) {
    18     int m = arr.size();
    19     int sum = 0;
    20     for (int i = 1; i < (1 << m); i++) {
    21         int fg = -1, ret = 1;
    22         for (int j = 0; j < m; j++) {
    23             if (i >> j & 1) {
    24                 ret *= arr[j]; fg = -fg;
    25             }
    26         }
    27         sum = sum + fg * cnt[ret];
    28         cnt[ret] += 1;
    29     }
    30     return sum;
    31 }
    32 
    33 void work() {
    34     scanf("%d", &n);
    35     for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
    36     sort(a + 1, a + 1 + n);
    37     memset(cnt, 0, sizeof(cnt));
    38     for (int i = 1; i <= n; i++) {
    39         ans[i][0] = calc(prime[a[i]]);
    40     }
    41     memset(cnt, 0, sizeof(cnt));
    42     for (int i = n; i >= 1; i--) {
    43         ans[i][1] = calc(prime[a[i]]);
    44     }
    45     lld Sum = (lld)n * (n-1) * (n-2) / 6;
    46     lld A = 0;
    47     lld B = 0;
    48     for (int i = 1; i <= n; i++) {
    49         A += ans[i][0] * (i-1 - ans[i][0]);
    50         A += ans[i][1] * (n-i - ans[i][1]);
    51         B += ans[i][0] * ans[i][1];
    52         B += (i-1 - ans[i][0]) * (n-i - ans[i][1]);
    53     }
    54     printf("%I64d
    ", B-A+Sum >> 1);
    55     return ;
    56 }
    57 
    58 int main() {
    59     for (int i = 2; i <= 1e5; i++) {
    60         if (!check[i]) {
    61             for (int j = 1; j * i <= 1e5; j++) {
    62                 check[j * i] = 1;
    63                 prime[j*i].push_back(i);
    64             }
    65         }
    66     }
    67     int T;
    68     scanf("%d", &T);
    69     for (int cas = 1; cas <= T; cas++) work();
    70     return 0;
    71 }
    View Code
  • 相关阅读:
    【CF 547E】 Mike and Friends
    [LNR#2 D1T3] 不等关系
    [THUPC2019] 不等式
    [THUPC2019]过河卒二
    [THUPC2018] 绿绿和串串
    【IOI2018】组合动作
    229. Majority Element II My Submissions Question
    169. Majority Element My Submissions Question
    ### Caffe
    ### OpenCV安装(Linux)
  • 原文地址:https://www.cnblogs.com/danceonly/p/4043963.html
Copyright © 2011-2022 走看看