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

数论各种小定理

三个重要的同余公式

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. CNN for NLP

    卷积神经网络在自然语言处理任务中的应用.参考链接:Understanding Convolutional Neural Networks for NLP(2015.11) Instead of ima ...

  2. PHP程序员的技能图谱

    PHP知识图谱      

  3. PHP底层运行机制与原理

    PHP的设计理念及特点 多进程模型:由于PHP是多进程模型,不同请求间互不干涉,这样保证了一个请求挂掉不会对全盘服务造成影响,当然,时代发展,PHP也早已支持多线程模型. 弱类型语言:和C/C++.J ...

  4. [易学易懂系列|rustlang语言|零基础|快速入门|(24)|实战2:命令行工具minigrep(1)]

    [易学易懂系列|rustlang语言|零基础|快速入门|(24)|实战2:命令行工具minigrep(1)] 项目实战 实战2:命令行工具minigrep 有了昨天的基础,我们今天来开始另一个稍微有点 ...

  5. zeromq实践

    zeromq简介 zeroMQ不是TCP,不是socket,也不是消息队列,而是这些的综合体. ZeroMQ以嵌入式网络编程库的形式实现了一个并行开发框架(concurrency framework) ...

  6. 第十一章 前端开发-JavaScript

    第十一章 前端开发-JavaScript 11.3.1 js引入方式 行内样式 <p id="" class="" style="" ...

  7. 07 saltstack生产实例-mysql主从

    1.服务部署 .服务部署 抽象:功能模块 redis 安装.配置.启动 mysql 安装.配置(my.cnf可以统一 目录默认配置可以统一) master: server_id slave: serv ...

  8. Cannot use JSX unless the '--jsx' flag is provided.

    在tsx文件中加入html代码后,报错 Cannot use JSX unless the '--jsx' flag is provided. 解决方法: 在tsconfig.json中加入: &qu ...

  9. 【JZOJ5801】【2018.8.12省选模拟】circular

    题目大意 分析 把环拆开 线段其实就是区间 对于每个区间,向在TA后面并且b_i最小的区间连边, 然后从每个区间(ai,bi)开始,在保证跳到的区间(aj,bj),bj<=ai+m的情况下向后倍 ...

  10. postman 跟restsharp 模拟请求http

    https://github.com/restsharp/RestSharp postman 生成的访问代码: 好用! Features Assemblies for .NET 4.5.2 and . ...