Educational Codeforces Round 37-G.List Of Integers题解
一、题目
二、题目链接
http://codeforces.com/contest/920/problem/G
三、题意
给定一个$t$,表示有t次查询。每次查询给定一个$x$, $p$, $k$,需要输出一个大于$x$、与$p$互质、第$k$大的数字。如样例1所示,比$7$大、与$22$互质、第$1$大的数字是$9$,第$2$大的数字是$13$,第$3$大的数字是$15$。
四、思路
二分+容斥原理。
二分一个数字$mid$,看看$[x+1,mid]$之间与$p$互质的数的个数。需要注意的是,如果个数是$k$,还要判断二分的$mid$是不是与$p$互质。如果是,说明要输出的值在$[x+1, mid)$之间,要需要继续做二分。(注意括号样式哦)
统计$[x+1, mid]$之间与$p$互质的数的个数,方法是:把这个区间内$p$的素因子的倍数全部筛掉,剩余的就是与$p$互质的了。在筛的过程中,比如$p$是$12$,素因子是$2$、$3$,筛掉$2$的倍数的方法是:区间长度$len - (mid / 2 - x / 2)$。同理,筛掉$3$的倍数的方法也一样。但是,对于所有$6$的倍数,会被减两次,所以,需要再加一次。而这个过程,其实就是容斥原理。
在这个题目中,利用容斥原理统计个数时,有两个写法:
1、每次二分一个上界值$mid$,就枚举二进制;
2、保存所有的询问,对每个询问的$p$,都预处理出它的所有素因子组合的乘积。然后,再枚举每一个询问,传入二分上界值$mid$时,枚举预处理的$p$的所有素因子组 合的乘积即可。(详细的写法可参考源代码)
另外,还有一点,在做询问之前,需要预处理出$[1, 1e6]$区间内所有数字的素因子。
五、源代码
1、写法一:每次二分一个上界值$mid$,就枚举二进制;
#pragma GCC optimize(2) #pragma comment(linker, "/STACK:102400000, 102400000") #include<bits/stdc++.h> using namespace std; typedef long long LL; ; template <class T> inline void read(T &x) { int t; bool flag = false; ')) ; if(t == '-') flag = true, t = getchar(); x = t - '; + t - '; if(flag) x = -x; } bool prime[MAXN]; vector<LL> d[MAXN];//d[i]:数字i的所有素因子 void init() { ; ; i <= N; ++i)d[i].clear(), prime[i] = true; ; i <= N; ++i) { if(prime[i]) { for(int j = i + i; j <= N; j += i)prime[j] = false; } } ; i <= N; ++i) { if(prime[i]) { for(int j = i; j <= N; j += i)d[j].push_back(LL(i)); } } } /**[x+1, mid]**/ LL calc(LL x, LL p, LL mid) { LL res = mid - x; /*枚举二进制: 如果i=5,二进制为0101,从低位数起,第0位和第2位为1, 那么就取d[p]的第0个和第2个素因子,计算乘积,去做容斥操作。 同时,需要统计取得素因子的个数。 如果是奇数,那么,容斥操作中符号是+,否则是-。 */ , t = << d[p].size(); i < t; ++i) { LL cnt = , prod = ; ; j > ; j >>= , ++k) { ) { cnt++; prod *= d[p][k]; } } res -= (mid / prod - x / prod) * (cnt % == ? : -); } return res; } int main() { #ifndef ONLINE_JUDGE freopen("Ginput.txt", "r", stdin); #endif // ONLINE_JUDGE LL T, x, p, k, low, high, mid, ans = , tmp; init(); read(T); while(T--) { read(x), read(p), read(k); low = x, high = 1LL << ;/*这个地方要特别注意,写大了就超时。*/ ) { mid = (low + high) / ; tmp = calc(x, p, mid); if(tmp < k)low = mid; else if(tmp > k)high = mid; else { if(__gcd(mid, p) > 1LL)high = mid; else { ans = mid; break; } } } printf("%lld\n", ans); } ; }
2、保存所有的询问,对每个询问的$p$,都预处理出它的所有素因子组合的乘积。然后,再枚举每一个询问,传入二分上界值$mid$时,枚举预处理的$p$的所有素因子组 合的乘积;
#pragma GCC optimize(2) #pragma comment(linker, "/STACK:102400000, 102400000") #include<bits/stdc++.h> using namespace std; typedef long long LL; typedef tuple<LL, LL, LL> T3L; typedef pair<LL, LL> P2L; ; template <class T> inline void read(T &x) { int t; bool flag = false; ')) ; if(t == '-') flag = true, t = getchar(); x = t - '; + t - '; if(flag) x = -x; } bool prime[MAXN]; vector<LL> d[MAXN];/*d[i]:数字i的素因子*/ vector<P2L> f[MAXN];/*f[i]:数字i的素因子组合的乘积和该组合的素因子个数*/ vector<T3L> qs; void init() { ; qs.clear(); ; i <= N; ++i)d[i].clear(), f[i].clear(), prime[i] = true; ; i <= N; ++i) { if(prime[i]) { for(int j = i + i; j <= N; j += i)prime[j] = false; } } ; i <= N; ++i) { if(prime[i]) { for(int j = i; j <= N; j += i)d[j].push_back(LL(i)); } } } /**[x+1, mid]**/ LL calc(LL x, LL p, LL mid) { LL res = mid - x; ; i < f[p].size(); ++i) {/*直接枚举素因子组合的乘积*/ LL prod = f[p][i].first, cnt = f[p][i].second; res -= (mid / prod - x / prod) * (cnt % == ? : -); } return res; } int main() { #ifndef ONLINE_JUDGE freopen("Ginput.txt", "r", stdin); #endif // ONLINE_JUDGE LL T, x, p, k, low, high, mid, ans = , tmp; init(); read(T); ; i < T; ++i) { read(x), read(p), read(k); qs.push_back(make_tuple(x, p, k));/*保存所有询问*/ } /*预处理每个询问的p的素因子组合的乘积、组合个数。 写法同方法1。 */ ; t < T; ++t) { tmp = >(qs[t]); ) { , top = << d[tmp].size(); i < top; ++i) { LL cnt = , prod = ; ; j > ; j >>= , ++k) { ) { cnt++; prod *= d[tmp][k]; } } f[tmp].push_back(make_pair(prod, cnt)); } } } ; t < T; ++t) { x = >(qs[t]), p = >(qs[t]), k = >(qs[t]); low = x, high = 1LL << ;/*这个地方要特别注意,写大了就超时。*/ ) { mid = (low + high) / ; tmp = calc(x, p, mid); if(tmp < k)low = mid; else if(tmp > k)high = mid; else { if(__gcd(mid, p) > 1LL)high = mid; else { ans = mid; break; } } } printf("%lld\n", ans); } ; }
Educational Codeforces Round 37-G.List Of Integers题解的更多相关文章
- Educational Codeforces Round 37 G. List Of Integers (二分,容斥定律,数论)
G. List Of Integers time limit per test 5 seconds memory limit per test 256 megabytes input standard ...
- Educational Codeforces Round 37
Educational Codeforces Round 37 这场有点炸,题目比较水,但只做了3题QAQ.还是实力不够啊! 写下题解算了--(写的比较粗糙,细节或者bug可以私聊2333) A. W ...
- Educational Codeforces Round 37 (Rated for Div. 2)C. Swap Adjacent Elements (思维,前缀和)
Educational Codeforces Round 37 (Rated for Div. 2)C. Swap Adjacent Elements time limit per test 1 se ...
- Educational Codeforces Round 63 (Rated for Div. 2) 题解
Educational Codeforces Round 63 (Rated for Div. 2)题解 题目链接 A. Reverse a Substring 给出一个字符串,现在可以对这个字符串进 ...
- Educational Codeforces Round 65 (Rated for Div. 2)题解
Educational Codeforces Round 65 (Rated for Div. 2)题解 题目链接 A. Telephone Number 水题,代码如下: Code #include ...
- Educational Codeforces Round 64 (Rated for Div. 2)题解
Educational Codeforces Round 64 (Rated for Div. 2)题解 题目链接 A. Inscribed Figures 水题,但是坑了很多人.需要注意以下就是正方 ...
- Educational Codeforces Round 58 (Rated for Div. 2) 题解
Educational Codeforces Round 58 (Rated for Div. 2) 题目总链接:https://codeforces.com/contest/1101 A. Min ...
- Educational Codeforces Round 60 (Rated for Div. 2) 题解
Educational Codeforces Round 60 (Rated for Div. 2) 题目链接:https://codeforces.com/contest/1117 A. Best ...
- Educational Codeforces Round 37 (Rated for Div. 2) G
G. List Of Integers time limit per test 5 seconds memory limit per test 256 megabytes input standard ...
- codeforces 920 EFG 题解合集 ( Educational Codeforces Round 37 )
E. Connected Components? time limit per test 2 seconds memory limit per test 256 megabytes input sta ...
随机推荐
- Gym 101334F Feel Good
http://codeforces.com/gym/101334 题意:给定一串数,求一个区间,使得该区间的所有数之和乘以该区间内最小的数的乘积最大. 思路:先预处理一下,计算出前缀和. 我们可以把每 ...
- nodejs使用multiparty模块实现文件上传(另附express.bodyParser()的说明)
最近师弟师妹们在用formidable做文件上传的时候会出现form.parse()不会触发的问题,在stackoverflow也没有找到答案,反而是几个答案推荐使用multiparty来代替,因为那 ...
- linux-android-adt
本打算带着唐帅弟弟研究几天手机开发,没想到这老弟天天遇到问题,原来认为他除了错误,没想到啊,我一上手也到处 是错误,折磨我们哥俩了,今天我俩干 了几把扑克,PK了一次羽毛球,回来研究了一会,阿门问题解 ...
- 理解Javascript的Event Loop
一.单线程 js作为浏览器脚本语言,他的主要用途是与用户交互,以及操作DOM,这决定了它只能是单线程,为什么呢?因为假如js同时有两个线程,一个线程是在DOM上增加内容,另一个线程是删除这个节点,那么 ...
- Java——基本概念
body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...
- Sizzle源码分析:一 设计思路
一.前言 DOM选择器(Sizzle)是jQuery框架中非常重要的一部分,在H5还没有流行起来的时候,jQuery为我们提供了一个简洁,方便,高效的DOM操作模式,成为那个时代的经典.虽然现在Vue ...
- C++设计模式之组合模式
DP书上给出的定义:将对象组合成树形结构以表示“部分-整体”的层次结构.组合使得用户对单个对象和组合对象的使用具有一致性.注意两个字“树形”.这种树形结构在现实生活中随处可见,比如一个集团公司,它有一 ...
- ISE创建Microblaze软核(二)
ISE创建Microblaze软核(二) (2012-07-13 15:09:08) 转载▼ 标签: 杂谈 分类: FPGA开发 第四步 进入Platform Studio操作界面 通过向导创建软核后 ...
- 关于CMD中延迟环境变量嵌套的实现方法
在我昨天做的一个bat中(自动按日期重命名文件名)涉及到这方面的问题 以前涉及到这里时就想别的办法替代过去,今天好好扒出来说说: 实现变量嵌套的2种方法: 1,使用call实现变量嵌套 变量嵌套:即在 ...
- show()是非模式窗体. showDialog()是模式窗体.
show()仅仅是显示出来窗口界面而已```也就是和你执行的结果在同一窗口显示```所显示的窗口可以在后台运行```而showDialog()是一个对话框窗口界面```执行结果以新窗口界面出现```不 ...