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

数论各种小定理

三个重要的同余公式

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. Selenium(1)

    一.Selenium->Se(硒)->功能自动化测试工具=功能自动化测试工具(QTP)<-Mercury(汞) 1.Selenium介绍 (1)Selenium 是针对web被测系统 ...

  2. BZOJ 1003 最短路dp

    物流公司要把一批货物从码头A运到码头B.由于货物量比较大,需要n天才能运完.货物运输过程中一般要转停好几个码头.物流公司通常会设计一条固定的运输路线,以便对整个运输过程实施严格的管理和跟踪.由于各种因 ...

  3. Django 中 cookie的使用

    Cookie是浏览器在客户端留下的一段记录,这段记录可以保留在内存或者硬盘上.因为Http请求是无状态的,通过读取cookie的记录,服务器或者客户端可以维持会话中的状态.比如一个常见的应用场景就是登 ...

  4. 小程序+tgit

    1.微信公众平台-设置-开发者工具  开通 腾讯云和tgit权限管理 如果遇到问题 ..用户二次验证什么的   直接去 腾讯云-安全设置 将“敏感操作”和“异地登陆” 中的保护去掉 2.微信公众平台- ...

  5. linux内核 概念

    内核Kernel只是操作系统的一部分,操作系统本身在内核之上还包含命令行shell和其他种类的用户界面. 通常内核包含: 中断服务程序 进程管理和调度程序 内存管理程序 进程同步方法 IO和设备等 在 ...

  6. 解决使用vue打包时vendor文件过大或者是app.js文件很大的问题

    这篇文章主要介绍了使用vue打包时vendor文件过大或者是app.js文件很大问题的解决方法,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下 第一次使用vue2.0开发,之前都是用的angu ...

  7. 08-sp_who2和inputbuffer的使用,连接数

    一.sp_who2的使用 1.存储过程的位置 sp_who官方解释地址:https://docs.microsoft.com/zh-cn/sql/relational-databases/system ...

  8. python2.6切换python3.4的操作记录

    python2.6切换python3.4的操作记录 之所以写这个记录,源于昨日下午,因为开发人员使用脚本清洗数据,而导致生产环境数据异常,需要根据binlog日志进行回滚.但在使用binlog2sql ...

  9. .Net中手动实现AOP

    序言 资料 https://www.cnblogs.com/farb/p/AopImplementationTypes.html

  10. 从零开始入门 K8s | Kubernetes 调度和资源管理

    作者 | 子誉  蚂蚁金服高级技术专家 关注"阿里巴巴云原生"公众号,回复关键词"入门",即可下载从零入门 K8s 系列文章 PPT. Kubernetes 调 ...