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

数论各种小定理

三个重要的同余公式

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. Matrix Factorization in RecSys

    矩阵分解在推荐系统中的应用. 参考链接:知乎. 传统SVD,Funk-SVD,Bias-SVD,SVD++. SVD奇异值分解及其意义. 漫谈奇异值分解.

  2. 小程序+tgit

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

  3. 二维数组转化为json数组

    二维数组转化为json数组 -1 var colName = [ ["08020092", "AVX", "1200m", "12 ...

  4. 201871010105-曹玉中《面向对象程序设计(java)》第十七周学习总结

    201871010105-曹玉中<面向对象程序设计(java)>第十七周学习总结 项目 内容 这个作业属于哪个过程 https://www.cnblogs.com/nwnu-daizh/ ...

  5. 在jquery中,使用ajax上传文件和文本

    function onSubmit (data) { //获取文本 var callingContent = $('#callingContent').val() // 获取文件 var files ...

  6. 快速拿下CSS盒子模型

    下面的图片就是Chrome浏览器审查元素里的盒子情况展示,我们可以看到一个容器由4个颜色代表的内容组成:内容(content).填充(padding).边框(border).边界(margin),在这 ...

  7. 51 Nod 1092 回文字符串

    1092 回文字符串  基准时间限制:1 秒 空间限制:131072 KB 分值: 10 难度:2级算法题  收藏  关注 回文串是指aba.abba.cccbccc.aaaa这种左右对称的字符串.每 ...

  8. elastic search&logstash&kibana 学习历程(二)es基础知识

    简介:es的index索引,document文档对象,副本,多节点集群等基础知识 1.通俗的解释: 在Elasticsearch中,文档归属于一种类型(type),而这些类型存在于索引(index)中 ...

  9. 24.Python比较运算符(关系运算符

    比较运算符,也成关系运算符,用于对常量.变量或表达式的结果进行大小.真假等比较,如果比较结果为真,则返回 True:反之,则返回 False. Python 支持的比较运算符如表 1 所示. 表 1 ...

  10. $message的问题

    项目中出现$message的问题: 拉取数据成功后 this.$message.success("数据拉取成功")点击拉取第一次不出现,但是代码执行了,后来多次点击就出现了 原因: ...