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

数论各种小定理

三个重要的同余公式

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. Linux之top 监视系统任务的工具

    top 监视系统任务的工具: 和ps 相比,top是动态监视系统任务的工具,top 输出的结果是连续的:  top 命令用法及参数: top 调用方法: top 选择参数 参数: -b  以批量模式运 ...

  2. ThinkPHP胜出Laravel 近4倍,主流框架性能测试

    主流PHP框架性能非权威测试 作为一个PHP开发者,而且是初创企业团队的技术开发者,选择开发框架是个很艰难的事情. 用ThinkPHP的话,招聘一个刚从培训机构出来的开发者就可以上手了,但是性能和后期 ...

  3. (七)zabbix监控nginx

    1.agent端配置 1)nginx编译安装需要加上该选项--with-http_stub_status_module 2)修改nginx配置文件 #vim /usr/local/nginx/conf ...

  4. regex正则

    1 正则表达式基本语法 两个特殊的符号^和$.他们的作用是分别指出一个字符串的开始和结束.例子如下: ^The:表示所有以”The”开始的字符串(”There”,”The cat”等): of des ...

  5. Storm实践(一):基础知识

    storm简介 Storm是一个分布式实时流式计算平台,支持水平扩展,通过追加机器就能提供并发数进而提高处理能力:同时具备自动容错机制,能自动处理进程.机器.网络等异常. 它可以很方便地对流式数据进行 ...

  6. $'\r': command not found

    在Linux下执行程序最省事的方式就是将系统的执行流程封装成一个shell脚本,上传到linux环境中后就可以直接执行了,但是今天在具体实施的时候出现了错误 $'\r': command not fo ...

  7. Django项目开发,XSS攻击,图片防盗链,图片验证码,kindeditor编辑器

    目录 一.Django项目开发 1. 项目开发流程 2. auth模块的补充 (1)django的admin可视化管理页面 (2)将admin可视化管理页面的模型表显示成中文 (3)auth模块的用户 ...

  8. noi.ac #531 神树和物品

    题目链接:戳我 决策单调性 (蒟蒻终于会写决策单调性啦!考试全场切这题就我不会啊嘤) (证明?不会啊,自己打表看QAQ) 44pts \(O(n^2)\)代码: #include<iostrea ...

  9. CentOS7下安装mysql5.1 或升级到5.7 以及小问题的解决方案

     正文开始 1.首先打开终端输入以下内容下载mysql5.1的repo源(安装5.7从第二步执行) wget http://repo.mysql.com/mysql-community-release ...

  10. ubuntu 下vscode 修改主题 注释斜体

    找到vscode的程序目录 全局搜索extensions 找到目录 /home/your_usr_name/.vscode/extensions 这里修改 注释字体 直接删掉fontStyle for ...