南理第八届校赛同步赛-C count_prime//容斥原理
大致思路就是先求出n的质因数假设是a1-an,然后在1-a的区间里面查找至少能整除{a1,a2...an}中一个元素的数有多少个,对1-b也做相同的处理,而找出来的元素肯定是与n不互质的,那么把区间的长度减去元素的个数就是那个区间里面与n互质的数的个数了,然后1-b的减去1-(a-1)的就是答案了。
而在1-a的区间里面查找至少能整除{a1,a2...an}中一个元素的数有多少个,这里就要用到容斥原理了。
首先来看容斥原理
在计数时,必须注意没有重复,没有遗漏。为了使重叠部分不被重复计算,人们研究出一种新的计数方法,这种方法的基本思想是:先不考虑重叠的情况,把包含于某内容中的所有对象的数目先计算出来,然后再把计数时重复计算的数目排斥出去,使得计算的结果既无遗漏又无重复,这种计数的方法称为容斥原理。
就比如质因数有2,3 然后1-10里面能整除2的有2,4,6,8,10;能整除3的有3,6,9;把这个看作成集合A,集合B,|A∩B|=1,|A|=5,|B|=3,|A∪B|=|A|+|B|-|A∩B|;
将这个公式推广到n个集合
回到题目,考虑质因子{a1,a2,a3..an},那么在[1-r]有多少个数能整除ai,答案就是[r/ai],但是单纯的把答案加上去肯定是错的(有些数可能被好几个质因子整除),这个时候就用到容斥原理来解决。
假设有m个质因子,那么就有2^m-1种情况(lcm(...),中间填入数字,每个数字都有两种选择,填还是不填,但不能全部都不填对吧);
附上模板
int solve (ll n, ll r)
{ vector<ll> p;
p.clear();
for (int i=; i*i<=n; ++i)
if (n % i == )
{
p.push_back (i);
while (n % i == )
n /= i;
}
if (n > )
p.push_back (n);
//分解质因数
ll sum = ;
ll cur;
ll mult = ;
ll bits = ;
ll s=<<p.size();
for (ll msk=; msk<s; msk++)
{ mult = ;
bits = ;
for (int i=; i<p.size(); ++i)
if (msk & (<<i))
{
bits++;
mult *= p[i]; }
cur = r / mult;
if (bits % == )
sum += cur;
else
sum -= cur; }
//printf("%lld\n",sum);
return r - sum;//1-r与n互质的数的个数 }
我把模板里面的位运算解释一下吧,p.size()代表n的质因数有多少个,而1<<p.size()就是2^(p.size()),mult表示某几个质因数的最小公倍数,bits表示集合的个数,用msk把1->p.size()-1里面所有的数用二进制表示出来,而if(a&b)表示a和b的二进制表示有没有相同的一位都为1,如果有就为真,没有就为假,现在假如有一个数30,那么它的质因数有2,3,5,那么一共有001,010,011,100,101,110,111,这七种情况,在里面的第二个循环其实就是为了读取msk的二进制有哪几位是1,因为二进制把所有的情况都包括了,就比如001,001&001=1,其他的都为假,这个时候就读到了|A1|这种情况,即2,里面的循环1<<i,只能得到001,010,100这几个数,010&010=1,其他的都为假,这个时候就读到了|A2|这种情况,即3,011&001=1,011&010=1,这个时候就读取到了|A1∩A2|的情况,即2,3的最小公倍数即6,而由于容斥原理当里面的集合有偶数个的时候是要减去这个集合里面元素的数量的,所以这个时候就知道了|A1|+|A2|-|A1∩A2|,
100&100=1,这个时候读到了|A3|,
101&001=1,101&100=1,这个时候读到了|A1∩A3|,
110&100=1,110&010=1,这个时候读到了|A2∩A3|,
111&001=1,111&010=1,111&100=1,这个时候读到了|A1∩A2∩A3|,
到这个时候所有的情况已经全部都读取完毕了,然后按照在[1-r]有多少个数能整除ai,答案就是[r/ai]这种性质,就能求出每个集合里面元素的数量,然后按照容斥原理的公式相加减就好了。
那么答案就是套模板了
#include <stdio.h>
#include <iostream>
#include <vector>
using namespace std;
typedef long long ll;
vector<ll> p;
int solve (ll n, ll r)
{ p.clear();
for (int i=; i*i<=n; ++i)
if (n % i == )
{
p.push_back (i);
while (n % i == )
n /= i;
}
if (n > )
p.push_back (n);
//分解质因数
ll sum = ;
ll cur;
ll mult = ;
ll bits = ;
ll s=<<p.size();
for (ll msk=; msk<s; msk++)
{ mult = ;
bits = ;
for (int i=; i<p.size(); ++i)
if (msk & (<<i))
{
bits++;
mult *= p[i]; }
cur = r / mult;
if (bits % == )
sum += cur;
else
sum -= cur; }
//printf("%lld\n",sum);
return r - sum;//1-r与n互质的数的个数 }
int main()
{
ll a,b,n;
int t;
scanf("%d",&t);
while(t--)
{
scanf("%lld %lld %lld",&a,&b,&n);
ll r=solve(n,b);
ll l=solve(n,a-);
printf("%lld\n",r-l); }
}
南理第八届校赛同步赛-C count_prime//容斥原理的更多相关文章
- 南理第八届校赛同步赛-F sequence//贪心算法&二分查找优化
题目大意:求一个序列中不严格单调递增的子序列的最小数目(子序列之间没有交叉). 这题证明贪心法可行的时候,可以发现和求最长递减子序列的长度是同一个方法,只是思考的角度不同,具体证明并不是很清楚,这里就 ...
- 哈尔滨理工大学软件与微电子学院第八届程序设计竞赛同步赛(高年级) Solution
A: Solved. 分别处理出每个%7后余数的数字个数,再组合一下 #include <bits/stdc++.h> using namespace std; #define ll lo ...
- NOIP2013,复赛及同步赛,报名及比赛,专题页面
本通知的对象仅仅是福州第十九中学的学生 所有参加复赛以及同步赛的选手,请务必要仔细阅读:<关于CCF NOIP2013复赛有关事宜的通知>,里面有比赛的时间.地点.以及比赛费用的说明. 参 ...
- 山东省ACM多校联盟省赛个人训练第六场 poj 3335 D Rotating Scoreboard
山东省ACM多校联盟省赛个人训练第六场 D Rotating Scoreboard https://vjudge.net/problem/POJ-3335 时间限制:C/C++ 1秒,其他语言2秒 空 ...
- Minieye杯第十五届华中科技大学程序设计邀请赛现场同步赛 I Matrix Again
Minieye杯第十五届华中科技大学程序设计邀请赛现场同步赛 I Matrix Again https://ac.nowcoder.com/acm/contest/700/I 时间限制:C/C++ 1 ...
- NOI Day1线上同步赛梦游记
Preface 第一次体验NOI,虽然不是正式选手,但是打打同步赛还是挺涨姿势的,也算是体验了一把. Day1很爆炸,一方面是NOI题目的难度高于自身的水平,另一方面也出现了比较大的失误,T1一个数组 ...
- NOI 2018网络同步赛(游记?)
刚中考完那段时间比较无聊,报名了一个同步赛,报完名才发现成绩单是要挂到网上的,而且因为报的早给了一个很靠前的考号...那布星啊,赶紧学点东西,于是在一周内学了网络流,Treap以及一些数论. Day1 ...
- 10.17(山东多校联合模拟赛 day1)
山东多校联合模拟赛 day1 题不难 rect [问题描述] 给出圆周上的 N 个点, 请你计算出以这些点中的任意四个为四个角,能构成多少个矩形. 点的坐标是这样描述的, 给定一个数组 v[1..N] ...
- 【NOI 2019】同步赛 / 题解 / 感想
非常颓写不动题怎么办…… 写下这篇博客警示自己吧…… 游记 7.16 我并不在广二参加 NOI,而是在距离广二体育馆一公里远的包间打同步赛(其实就是给写不动题找个理由) 上午身体不舒服,鸽了半天才看题 ...
随机推荐
- Random()种子数
Random rand =new Random(25); int i; i=rand.nextInt(100); 初始化时25并没有起直接作用,rand.nextInt(100);中的100是随机数的 ...
- Python—包介绍
包(Package) 当你的模块文件越来越多,就需要对模块文件进行划分,比如把负责跟数据库交互的都放一个文件夹,把与页面交互相关的放一个文件夹, . └── my_proj ├── crm #代码目录 ...
- 机器学习第一篇——最近邻kNN
机器学习监督学习中,根据解决问题的连续性和离散型,分为分类问题和回归问题.最邻近算法kNN是一种最为直接和简便的分类方法. kNN本质上,是计算目标到模型的欧式距离,从而判定目标所属的类别. 首先,在 ...
- 牛客练习赛38 D 题 出题人的手环 (离散化+树状数组求逆序对+前缀和)
链接:https://ac.nowcoder.com/acm/contest/358/D来源:牛客网 出题人的手环 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 524288K,其他 ...
- PAT L2-020 功夫传人
https://pintia.cn/problem-sets/994805046380707840/problems/994805059118809088 一门武功能否传承久远并被发扬光大,是要看缘分 ...
- yolo buffer is too small for requested array
yolo.cfg 与 yolo.weights 版本一定要对应, darknet链接 https://github.com/pjreddie/darknet 下载后在cfg文件夹下找到yolov2的配 ...
- 获取打开页面时的当前时间(yyyy-MM-dd hh:mm:ss)
Date.prototype.Format = function (fmt) { var o = { "M+": this.getMonth() + 1, //月份 "d ...
- WPF通过DynamicResource实现给界面动态更换皮肤
在我们的程序中有时候需要去实现动态更换皮肤的效果,从而完成一些个性化的设置,那么我们究竟怎样去实现动态换皮肤的效果呢?那么我们经常用到的就是设置不同的Style,并且在主程序的xaml文件中通过Dyn ...
- html5 表單輸入類型
輸入類型有:email,url,number,range,Date pickers(工作機制是什麼),search, 有相關類型的輸入域,會對域進行驗證. 不同的瀏覽器並不一定都支持所有的輸入類型.
- idea中Lombok的使用
使用了lombok的注解(@Setter,@Getter,@ToString,@@RequiredArgsConstructor,@EqualsAndHashCode或@Data)之后,就不需要编写或 ...