HDU5072 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\n", 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 }

时间: 2024-12-15 04:58:22

HDU5072 Coprime (乱搞?)的相关文章

UVA 11853 [dfs乱搞]

/* 大连热身E题 不要低头,不要放弃,不要气馁,不要慌张 题意: 在1000×1000的格子内有很多个炮弹中心,半径给定. 为某人能否从西部边界出发,从东部边界走出. 不能输出不能,能的话输出最北边的入口和出口的坐标. 思路: dfs乱搞题.把炮弹辐射范围连在一起的炮弹看作一个整体,记录下它围起来的边界区域. 然后找到最北边的输出. */ #include<bits/stdc++.h> using namespace std; double x[1005],y[1005],r[1005];

Codeforces 732e [贪心][stl乱搞]

/* 不要低头,不要放弃,不要气馁,不要慌张 题意: 给n个插座,m个电脑.每个插座都有一个电压,每个电脑都有需求电压. 每个插座可以接若干变压器,每个变压器可以使得电压变为x/2上取整. 有无限个变压器供应. 问最多能使得多少个插座与电脑匹配,使得电压一致. 如果有多种方案,输出需要变压器总数最小的那种. 输出匹配数量 输出每个插座需要接多少个变压器.输出每台电脑匹配哪个插座. 思路: 贪心 乱搞 先从小到大将插座排序,然后从地第一个插座开始,不断除以2上取整.不断找是否可以匹配.找到匹配就停

学渣乱搞系列之dp斜率优化

学渣乱搞系列之dp斜率优化 By 狂徒归来 貌似dp的斜率优化一直很难搞啊,尤其是像我这种数学很挫的学渣,压根不懂什么凸包,什么上凸下凸的,哎...说多了都是泪,跟wdd讨论了下,得出一些结论.本文很大部分参考了大神Accept的文章,不过此神貌似早已绝迹江湖,这篇文章写得好,也写得很差,前半部分叙述得很好,可是关键,关键部分说得很乱,有些许错误,很多大神都进行了评论指出,但是大神Accept貌似没有修改的意思,故重新总结下,以便自己以后查阅和复习啊. 下面看一个例题Print Article.

Bucharest, Romania 2013 H Red John Game 乱搞 未解

题意:给你一个无限的棋盘,里面有n×n的棋子,每个棋子可以跳过一个相邻(4个方向)棋子跳到下一个位置,并把他的相邻位(他跳过的那一位)删除. 解题思路:判断n%3 是否等于 0 , 原因未知. 解题代码: 1 #include<stdio.h> 2 int main(){ 3 int n ; 4 while(~scanf("%d",&n)) 5 { 6 if(n%3) 7 printf("1\n"); 8 else printf("0\

【BZOJ-4692】Beautiful Spacing 二分答案 + 乱搞(DP?)

4692: Beautiful Spacing Time Limit: 15 Sec  Memory Limit: 128 MBSubmit: 46  Solved: 21[Submit][Status][Discuss] Description 文章是一些单词组成的序列,单词由字母组成.你的任务是将一篇文章的单词填充到一个网格中,其中网格包含W列和足够多的行.为了布局之美,以下限制都需要满足. 1.文章中的文字需要按照原有的顺序放置.下图表示了将4个单词的文章“This is a pen”放入

【BZOJ-3578】GTY的人类基因组计划2 set + map + Hash 乱搞

3578: GTY的人类基因组计划2 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 367  Solved: 159[Submit][Status][Discuss] Description GTY召唤了n个人来做实验,GTY家的房子很大,有m个房间一开始所有人都在1号房间里,GTY会命令某人去某个房间等待做实验,或者命令一段区间的房间开始实验,实验会获得一些实验信息点数,点数为房间里的人数,如果一个房间里的一群人已经做过实验了那么这些人将不会增

hdu 4972 A simple dynamic programming problem (转化 乱搞 思维题) 2014多校10

题目链接 题意:给定一个数组记录两队之间分差,只记分差,不记谁高谁低,问最终有多少种比分的可能性 分析: 类似cf的题目,比赛的时候都没想出来,简直笨到极点..... 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <cmath> 6 #include <vector> 7 #include &

学渣乱搞系列之扩展KMP的那点事

扩展KMP牵涉了一些相对运动的姿势,比较费解!本学渣看了一天的扩展KMP,打算写点东西...本文看后,出现的后果本人一概不负责.毕竟我不是很会表达. 扩展KMP是搞什么灰机的?本学渣所知道的扩展KMP是来解集训篇那道字符串题的.有了犯罪动机,现在就要下手.不要以为扩展KMP就以为与KMP关系暧昧.屁大点事,两个根本不是一个东西.只是有点思想是一致的,就是利用已经匹配的信息避免一些不必要的匹配. 以此提高匹配速度.不过扩展KMP也能干KMP干的事.但是速度没KMP那么快. 扩展KMP要造两个数组,

【BZOJ 4148】 4148: [AMPPZ2014]Pillars (乱搞)

4148: [AMPPZ2014]Pillars Time Limit: 5 Sec  Memory Limit: 256 MBSec  Special JudgeSubmit: 100  Solved: 49 Description 给定一个n*m的矩形,其中有f个2*2的障碍物,其中任意两个障碍物中心之间的欧几里得距离至少为6, 且每个障碍物的中心到边缘的距离至少为3.请找到一条从左下角(1,1)出发经过所有没有障碍物的点各 一次的且最后回到左下角的回路. Input 第一行包含三个整数n,