本章内容对我来说真的是学的稀里糊涂的,除了前两题吭哧吭哧独立完成,第三题参考了别人的思路外,其余题目均是现学现卖,有点迷啊。所以写这篇博客的目的是先记录下聚聚们对本章内容相关重点的要求,并搜集一些相关资料,慢慢学吧。

数论各种小定理

三个重要的同余公式

D - GCD & LCM Inverse

题意:

给出两个整数 m、n ( < 2^63),求出两个整数 a、b ,使gcd(a, b)=m , lcm(a, b)=n ,并取 a + b 值最小的那一组。

Thinking:

拿到题看到数据范围后想了想没有思路。看了很多博客,对此题的化简分析有了认识,但实现本题所用的很多知识:

如:Miller-Rabin素性测试算法 和 进行素数分解的Pollard_Rho算法 却一头雾水。

在这里贴上一些博客供以后学习使用:
1、 https://blog.csdn.net/ECNU_LZJ/article/details/72675595

2、 https://blog.csdn.net/semiwaker/article/details/60142102

3 、https://blog.csdn.net/maxichu/article/details/45459533

4 、https://www.cnblogs.com/Norlan/p/5350243.html

5 、https://wenku.baidu.com/view/fbbed5a5f524ccbff12184af.html

通过化简使gcd(a1, b1)=1, 则 lcm(a1, b1)=n/m=s , 把s分解成两互质数s1, s2相乘的形式,这里由于n的范围过大,所以需要用到Miller_Rabin和Pollard_Rho算法将s分解。

要是a+b最小,则要使s1和s2越接近(初中的不等式知识可以证明),此处需要用到dfs()枚举s的num个互质的数如何组合成s1,s2并满足其差最小(这种枚举技巧学习了)。

(代码借鉴了很多前辈的,因为太多就不贴出处了,但还是要说声谢谢分享。)

 #include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
using namespace std;
#define LL long long LL qmul(LL a, LL b, LL c){
a %= c;
b %= c;
LL res = ;
while(b){
if(b&){
res = (res+a)%c;
}
a = (a+a)%c;
b >>= ;
}
return res;
}
LL qmodx(LL a, LL b, LL c){
a %= c;
b %= c;
if(c <= )
return a * b % c;
return (a * b - (LL)(a / (long double)c*b + 1e-) *c + c) % c;
}
LL qmod(LL a, LL b, LL c){
LL res = ;
while(b){
if(b&){
res = qmul(res, a, c);
}
b >>= ;
a = qmul(a, a, c)%c;
}
return res;
}
//以a为基,n-1=x*2^t a^(n-1)=1(mod n) 验证n是不是合数
//一定是合数返回true,不一定返回false
/*//////
?????
*////////
bool check(LL a, LL n, LL x, LL t){
LL ret = qmod(a, x, n);
LL last = ret;
for(int i=; i<=t; i++){
ret = qmul(ret, ret, n);
if(ret == && last!= && last!=(n-)) return true;
last = ret;
}
if(ret != ) return true;
return false;
}
////////----------
// Miller_Rabin()算法素数判定
//是素数返回true.(可能是伪素数,但概率极小)
//合数返回false;
bool Miller_Rabin(LL n, int S){
if(n < ) return false;
if(n == ) return true;
if((n&) == ) return false;
LL x = n-, t = ;
while((x&) == ){
x >>= ;
t++;
}
for(int i=; i<S; i++){
LL a = rand()%(n-) + ;
if(check(a, n, x, t)){
return false;
}
}
return true;
}
///////////------------
//************************************************
//pollard_rho 算法进行质因数分解
//************************************************
///////////----------
int factor[];//质因数分解结果(刚返回时是无序的)
int tol;//质因数的个数。数组小标从0开始
LL gcd(LL a, LL b){
if(a==) return ;
if(a < ) return gcd(-a, b);
while(b){
LL t = a % b;
a = b;
b = t;
}
return a;
}
LL Pollard_rho(LL x, LL c){
LL i = , k = ;
LL x0 = rand()%x;
LL y = x0;
while(){
i++;
x0 = (qmul(x0, x0, x) + c)%x;
LL d = gcd(y-x0, x);
if(d != && d != x) return d;
if(y == x0) return x;
if(i == k){
y = x0;
k += k;
}
}
}
void findfac(LL n){
if(Miller_Rabin(n, )){
factor[tol++] = n;
return;
}
LL p = n;
while(p >= n){
p = Pollard_rho(p, rand()%(n-)+);
}
findfac(p);
findfac(n/p);
}
///////---------
LL r[];
int num;
LL k, sq;
void dfs(LL now, int x){
if( now > sq ) return;
k = max(k, now);
for(int i=x; i<=num; i++){
dfs(now*r[i], i+);
}
} int main(){
LL gc, lc, n;
while(scanf("%lld%lld", &gc, &lc) != EOF){
if(gc == lc){
printf("%lld %lld\n", gc, lc);
continue;
}
tol = ;
n = lc/gc;
findfac(n); sort(factor, factor + tol);
num = ;
for(int i=; i<=; i++) r[i] = ;
r[num] = factor[];
for(int i=; i<tol; i++){
if(factor[i] == factor[i-]){
r[num] *= factor[i];
}else{
r[++num] = factor[i];
}
}
k = ; sq = (LL)sqrt(1.0*n);
dfs(, );
printf("%lld %lld\n", k*gc, lc/k);
}
return ;
}

F - GCD

题意: 求(1,b)区间和(1,d)区间里面gcd(x, y) = k的数的对数(1<=x<=b , 1<= y <= d)。注意[(x=5, y=7) and (x=7, y=5) are considered to be the same.]

听赵巨说此题有两种解法,可惜我都不会。

1、本题是一道莫比乌斯反演,就通过这道题了解并学习下。

同样贴出学习用到的博客地址:

  1. 初涉莫比乌斯反演
  2. 莫比乌斯反演详解
  3. 数论函数 - 莫比乌斯函数与莫比乌斯反演 - 基础杜教筛

下面给出两种mobius函数的求法:

 /*
时间复杂度O(nlogn)
这种筛法思路有点奇妙
*/
#include <cstdio>
const int maxn = ;
int mu[maxn+];
void get_mu1(){
for(int i=;i<maxn;++i){
int delta = (i== ? -mu[i] : -mu[i]);
mu[i]=delta;
for(int j=*i;j<N;j+=i)
mu[j]+=delta;
}
}
int main(){
get_mu1();
for(int i=; i<maxn; i++){
printf("i = %d mu[%d] = %d\n",i, i, mu[i]);
}
return ;
}
 /*
时间复杂度O(n)
这种筛法思路有点像 线性素数筛
去掉////则为线性素数筛法
*/
#include <cstdio>
const int maxn = ;
int mu[maxn+], p[maxn+], vis[maxn+];
void get_mu2(int &cnt){
mu[] = ;
cnt = ;
for(int i=; i<maxn; i++){
if(!vis[i]){
p[cnt++] = i;
mu[i] = -; ////
}
for(int j=; j<cnt && i*p[j]<maxn; j++){
vis[i*p[j]] = ;
if(i % p[j]){ ////
mu[i*p[j]] = -mu[i];
}else{
mu[i*p[j]] = ; ////
break;
}
}
}
}
int main(){
int cnt;
get_mu2(cnt);
for(int i=; i<maxn; i++){
printf("i = %d mu[%d] = %d\n",i, i, mu[i]);
}
return ;
}

本题最重要的应该是构造出 f 和 F 两函数并找出其关系,然后通过约数莫比乌斯反演或倍数莫比乌斯反演的转换。

比较难思考的是构造……

 #include <cstdio>
#include <algorithm>
using namespace std;
#define LL long long
const int maxn = 1e5+;
int mu[maxn+], p[maxn+], vis[maxn+];
void get_mu2(int &cnt){
mu[] = ;
cnt = ;
for(int i=; i<maxn; i++){
if(!vis[i]){
p[cnt++] = i;
mu[i] = -;
}
for(int j=; j<cnt && i*p[j]<maxn; j++){
vis[i*p[j]] = ;
if(i % p[j]){
mu[i*p[j]] = -mu[i];
}else{
mu[i*p[j]] = ;
break;
}
}
}
}
int main(){
int cnt;
get_mu2(cnt);
int T, a, b, c, d, k;
scanf("%d", &T);
for(int t=; t<=T; t++){
scanf("%d%d%d%d%d", &a, &b, &c, &d, &k);
printf("Case %d: ", t);
if(k == ){
printf("0\n");
continue;
}
b /= k; d /= k;
LL ans1 = , ans2 = ;
int mi = min(b,d);
for(int i=; i<=mi; i++){
ans1 += (LL)mu[i]*(b/i)*(d/i);
}
for(int i=; i<=mi; i++){
ans2 += (LL)mu[i]*(mi/i)*(mi/i);
}
printf("%lld\n", ans1-ans2/);
}
return ;
}

2、可以用欧拉函数+容斥原理,将问题求(1,n)和(1,m)内素数对的问题转化为   (1,n)内欧拉函数和(的问题)与 (1,n)和(n+1,m)内素数对(的问题)。

关于欧拉函数放上我学习过的文章:

  1. 欧拉函数求法与应用

第二个问题容斥原理有3种方法:队列数组   dfs   位运算

 #include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define LL long long
const int maxn = ;
int prime[maxn+];
//线性素数筛法筛出素数表
void getprime(){ //prime[0]记录素数表的长度
memset(prime, , sizeof(prime));
for(int i=; i<=maxn; i++){
if(!prime[i]){
prime[++prime[]] = i;
}
for(int j=; j<=prime[] && prime[j]<=maxn/i; j++){
//除法防溢出
prime[i*prime[j]] = ;
if(i%prime[j] == ) break;
}
}
}
// 算术展开
LL factor[][]; //[0][i]:第i个素数值 [1][i]:第i个素数的个数
int fatcnt;
void getfactors(LL x){
fatcnt = ;
LL tmp = x;
for(int i=; prime[i] <= tmp/prime[i]; i++){
factor[][fatcnt] = ;
if(tmp % prime[i] == ){
factor[][fatcnt] = prime[i];
while(tmp % prime[i] == ){
factor[][fatcnt]++;
tmp /= prime[i];
}
fatcnt++;
}
}
if(tmp != ){
factor[][fatcnt] = tmp;
factor[][fatcnt++] = ;
}
}
//欧拉函数打表
int euler[];
void geteuler(){
memset(euler, , sizeof(euler));
euler[] = ;
for(int i=; i<=; i++){
if(!euler[i]){
for(int j=i; j <= ; j += i){
if(!euler[j]){
euler[j] = j;
}
euler[j] = euler[j]/i*(i-);
}
}
}
}
//用位运算实现(1,n)内和m互质的个数 ////n<m
///这里代码比较好理解,可以对比赵巨讲的那个2R/7的例子,或者容斥的定义来写
int calc(int n, int m){
getfactors(m);
int ans = ;
///用二进制枚举m的几个素因子被用到
for(int i=; i < (<<fatcnt); i++){
int cnt = ;
int tmp = ;
for(int j=; j<fatcnt; j++){
//目前第几个因子被使用
if(i & (<<j)){
cnt++;
tmp *= factor[][j];
}
}
if(cnt & ){
ans += n/tmp;
}else{
ans -= n/tmp;
}//容斥原理
}
return (n - ans);
}
int main(){
getprime();
geteuler();
int a, b, c, d, k, T;
scanf("%d", &T);
for(int t=; t<=T; t++){
scanf("%d%d%d%d%d", &a, &b, &c, &d, &k);
printf("Case %d: ", t);
if(k== || k>b || k>d){
printf("0\n");
continue;
}
if(b > d) swap(b,d);
b /= k; d /= k;
LL ans = ;
for(int i=; i<=b; i++){
ans += (LL)euler[i];
}
for(int i=b+; i<=d; i++){
ans += (LL)calc(b, i);
}
printf("%lld\n", ans);
}
return ;
}

G - Semi-prime H-numbers

题意:

定义一个数,称之为H-numbers,性质:除4余1;

数分三种:1、unit即1;       2、H-primes:满足H-numbers性质的素数;     3、剩下的是H-composite;

H-semi-prime:两个H-prime相乘;

求h内有多少个H-semi-prime?

Thinking:

就按定义去筛出H-semi-prime数。

 #include <cstdio>
#include <cstring>
#define LL long long
const int maxn = ;
int hprime[maxn+];
int vis[maxn+];
int hcnt;
void getprime(){
for(int i=; i<=maxn; i+=){
for(int j=; (i*j<=maxn)&&(j<=maxn); j+=){
if(!vis[i] && !vis[j]){
vis[i*j] = ;
}else{
vis[i*j] = -;
//!(-1)==0
}
}
}
hcnt = ;
for(int i=; i<=maxn; i++){
if(vis[i] == ){
hcnt++;
}
hprime[i] = hcnt;
}
}
int main(){
getprime();
int h;
while(scanf("%d", &h) && h){
printf("%d %d\n", h, hprime[h]);
}
return ;
}

Day3 && Day4的更多相关文章

  1. Python--Day2/Day3/Day4(运算符、数据类型及内建函数)

    一.昨日内容回顾 Python种类:CPython(Python).JPython.IronPython.PyPy 编码: Unicode.UTF-8.GBK while循环 if...elif... ...

  2. 【Beta版本】七天冲刺——日志集合贴

    No Bug 031402401鲍亮 031402402曹鑫杰 031402403常松 031402412林淋 031402418汪培侨 031402426许秋鑫 Day1 Day2 Day3 Day ...

  3. 软件工程(FZU2015)赛季得分榜,第11回合(beta冲刺+SE总结)

    目录 第一回合 第二回合 第三回合 第四回合 第五回合 第6回合 第7回合 第8回合 第9回合 第10回合 第11回合 增补作业 积分规则 积分制: 作业为10分制,练习为3分制:alpha30分:b ...

  4. 【Alpha版本】十天冲刺——日志集合贴

    No Bug 031402401鲍亮 031402402曹鑫杰 031402403常松 031402412林淋 031402418汪培侨 031402426许秋鑫 Day1 Day2 Day3 Day ...

  5. 一起买beta版本文档报告汇总

    一起买beta版本文档报告汇总 031402401鲍亮 031402402曹鑫杰 031402403常松 031402412林淋 031402418汪培侨 031402426许秋鑫 一.Beta版本冲 ...

  6. 一起买Beta版本系列文档

    一起买beta版本文档报告汇总 031402401鲍亮 031402402曹鑫杰 031402403常松 031402412林淋 031402418汪培侨 031402426许秋鑫 一.Beta版本冲 ...

  7. 报错:对象必须实现 IConvertible;以分隔符进行分割链接concat_ws的使用方法;mysql数据类型转换cast,convert

    错误故障,mysql  服务器上用 concat_ws 函数,连接了一串数字,最后 服务器返回的字段就变成了一个 byte ,而我们想要的类型是  string 类型,那么转换的时候,就报错了. 正确 ...

  8. WC2019冬眠记

    Day0 报道日就当做Day0吧. 上午起床比较晚,起来就开始整理东西准备搬到广二的高中部去,搬了两趟,因为没吃早饭,头就很晕,吓得我赶快把之前发的士力架给吃了. 上午李姐姐和我们聊了聊\(THUWC ...

  9. 软件工程(FZU2015) 赛季得分榜,第11回合(beta冲刺+SE总结)

    SE_FZU目录:1 2 3 4 5 6 7 8 9 10 11 12 13 积分规则 积分制: 作业为10分制,练习为3分制:alpha30分:beta30分 团队项目分=团队得分+个人贡献分 个人 ...

随机推荐

  1. gluOrtho2D与glViewport

    https://blog.csdn.net/HouraisanF/article/details/83444183 窗口与显示主要与三个量有关:世界坐标,窗口大小和视口大小.围绕这些量共有4个函数: ...

  2. Dom修改元素样式

    提纲:我们可以通过js来修改元素的大小,颜色,位置等样式 1.element.style                         行内样式的操作 2.element.className    ...

  3. Acwing-204-表达整数的奇怪方式(扩展中国剩余定理)

    链接: https://www.acwing.com/problem/content/206/ 题意: 给定2n个整数a1,a2,-,an和m1,m2,-,mn,求一个最小的非负整数x,满足∀i∈[1 ...

  4. js 获取两个数组的交集,并集,补集,差集

    https://blog.csdn.net/piaojiancong/article/details/98199541 ES5 const arr1 = [1,2,3,4,5], arr2 = [5, ...

  5. 移动端rem使用及理解

    先上代码 window.onload = function(){ getRem(720,100) }; window.onresize = function(){ getRem(720,100) }; ...

  6. left join和right join和inner join

    此图仅限于理解他们之间的关系,下面还有举例,例子更好明白. left join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录  right join(右联接) 返回包括右表中的所有记录 ...

  7. 灰度图像--图像分割 霍夫变换(Hough Transform)--直线

    学习DIP第50天 转载请标明本文出处:http://blog.csdn.net/tonyshengtan ,出于尊重文章作者的劳动,转载请标明出处!文章代码已托管,欢迎共同开发:https://gi ...

  8. C#重绘TabControl

    C#重绘TabControl的Tabpage标签,添加图片及关闭按钮 Code highlighting produced by Actipro CodeHighlighter (freeware)h ...

  9. BZOJ 5330 Luogu P4607 [SDOI2018]反回文串 (莫比乌斯反演、Pollard Rho算法)

    题目链接 (BZOJ) https://www.lydsy.com/JudgeOnline/problem.php?id=5330 (Luogu) https://www.luogu.org/prob ...

  10. 微信小程序_(组件)可拖动movable-view

    微信小程序movable-view组件官方文档 传送门 Learn 一.moveable-view组件 一.movable-view组件 direction:movable-view的移动方向,属性值 ...