简单数论 | Day3 部分题解
A - The Euler function 来源:HDU 2824
计算[a,b]区间内的整数的欧拉函数值,需要掌握单个欧拉函数和函数表的使用。
#include <iostream>
#include <cstdio>
using namespace std; const int MAX_N = ;
typedef long long ll;
int phi[MAX_N];
// ll sum_phi[MAX_N]; 若使用前缀和累加,会爆内存(MLE) void phi_table(int n)
{ // 计算得到n以内的欧拉函数表,参考蓝书P121
int i, j;
for(i=;i<=n;i++)
phi[i] = i; for(i=;i<=n;i+=)
phi[i] /= ; for(i=3;i<=n;i+=)
{
if(phi[i]==i)
{
for(j=i;j<=n;j+=i)
phi[j] = phi[j] / i * (i - );
}
}
} int main()
{
phi_table();
// for(int i=1;i<=3000000;i++)
// sum_phi[i] = sum_phi[i-1] + phi[i];
// int a, b;
// while(cin>>a>>b)
// printf("%lld\n", sum_phi[b]-sum_phi[a-1]);
int a, b;
while(cin>>a>>b)
{
ll sum = ;
for(int i=a;i<=b;i++)
sum += phi[i];
printf("%lld\n", sum);
}
return ;
}
B - Divisors 来源:POJ 2992
求组合数C(n, k)的因子个数,0 ≤ k ≤ n ≤ 431。
打表可得431以内的素数只有83个,由于C(n, k) = n!/(k!*(n-k)!) = n*(n-1)*…*(n-k+1)/k!,开始的直观想法是求出分子上的每个素数因子的总个数,再减去分母上出现的每个素数因子的总个数,正约数的个数即为(a1+1)*(a2+1)*…*(an+1)。然而多次提交优化仍然超时。。。最后参考https://www.cnblogs.com/zxhyxiao/p/8026280.html,学到了计算N!中某个素因子个数的计算方法,结合网上的做法,终于AC。
求N!中素因子p的个数,也就是N!中p的幂次
公式为:cnt=[n/p]+[n/p^2]+[n/p^3]+...+[n/p^k]
核心代码:
int cnt = 0;
while(N)
{
cnt += N/p;
N /= p;
}
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std; int p[], cnt, num[];
bool notprime[]; void prime_table(int n)
{ // 筛素数
notprime[] = notprime[] = ;
int i, j;
for(i=;i<=n;i++)
{
if(!notprime[i])
{
num[i] = cnt;
p[cnt++] = i;
} for(j=;j<cnt && i*p[j]<n;j++)
{
notprime[i*p[j]] = ;
if(i%p[j]==) break;
}
}
} int main()
{ prime_table();
// for(int i=0;i<cnt;i++) cout<<p[i]<<endl;
// cout<<cnt<<endl;
int n, k;
while(scanf("%d %d", &n, &k)!=EOF)
{
long long ans = ;
for(int i=;i<cnt && p[i]<=n;i++)
{
int N = n, cnt = ;
while(N)
{
cnt += N/p[i];
N /= p[i];
}
N = k;
while(N)
{
cnt -= N/p[i];
N /= p[i];
}
N = n-k;
while(N)
{
cnt -= N/p[i];
N /= p[i];
}
ans *= (cnt+);
}
printf("%lld\n", ans);
}
return ;
}
C - Longge's problem 来源:POJ 2480
计算∑gcd(i, N), 1<=i<=N
简单推导可得所求结果为∑i*phi(n/i), i|n.由于n的上限太大(1e18),书上打表的办法失效,一时陷入困境。再次百度参考https://www.cnblogs.com/flipped/p/5690123.html才茅塞顿开,直接采用O(√n)求单个欧拉函数值。需要特别注意注释处,最开始好几次TLE都是因为i*i结果为int类型溢出变为负数,出现了死循环。
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std; typedef long long ll; ll euler(int x)
{ // 计算欧拉函数phi(x)
int res=x, m = (int)sqrt(x+0.5);
for(int i=; i<=m; i++)
if(x%i==)
{
res = res/i*(i-);
while(x%i==) x/=i;
}
if(x>) res = res/x*(x-);
return res;
} int main()
{
ll n, ans;
while(scanf("%lld", &n)!=EOF)
{
ans = ;
int i;
for(i=;i<n/i;i++) // for(i=1;(ll)i*i<n;i++)
{
if(n%i==) ans += i*euler(n/i) + n/i*euler(i);
}
if(i*i==n) ans += i*euler(i);
printf("%lld\n", ans);
}
}
E - Happy 2006 来源:POJ 2773
计算与m互质的第K大的正整数,m (1 <= m <= 1000000), K (1 <= K <= 100000000)
直接上AC代码:
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std; int gcd(int a,int b)
{
if(!b) return a;
return gcd(b,a%b);
} int euler(int x)
{
int res=x, m = (int)sqrt(x+0.5);
for(int i=; i<=m; i++)
if(x%i==)
{
res = res/i*(i-);
while(x%i==) x/=i;
}
if(x>) res = res/x*(x-);
return res;
} int main()
{
int m, k;
while(scanf("%d %d", &m, &k)!=EOF)
{
int sum = euler(m);
int t = k % sum, tt = , i;
if(t==) t = sum; //注意整除的处理
for(i=;i<m;i++)
{
if(gcd(i, m)==) tt++;
if(tt==t) break;
} printf("%d\n", i+(k-)/sum*m);
}
}
貌似以上做法的欧拉函数显得多余,直接用gcd判断m以内全部互质的整数,总个数即为sum。
D - GCD & LCM Inverse 来源:POJ 2429
最后AC的D题,参考了网上用dfs得到数组中最接近sqrt(N)的部分元素之积。晚上讲题解时滕佬指明一定要用Miller Rabin算法,直接在其模板基础上修改而来。代码十分长而且显得有些杂乱,日后再做整理吧~~
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <cmath>
#include <algorithm>
using namespace std; typedef long long ll; ll box[];
ll N, T, num; ll min(ll a , ll b)
{
return (a < b) ? a : b;
} ll gcd(ll a , ll b)
{
while(b)
{
ll t = a;
a = b;
b = t % b;
} return a;
} ll tim(ll a , ll b , ll mo)
{
a %= mo;
b %= mo; ll ans = ; while(b)
{
if(b & )
{
ans += a;
if(ans > mo)
ans -= mo;
} b >>= ;
a <<= ; if(a > mo)
a -= mo;
} return ans;
} ll po(ll x , ll n , ll mo)
{
x %= mo;
ll ans = ; while(n)
{
if(n & )
ans = tim(ans , x , mo); x = tim(x , x , mo);
n >>= ;
} return ans;
} bool tes(ll n , ll d , ll t , ll mo)
{ ll y = po(t , n , mo); ll i;
for(i = ; i < d ; i++)
{
ll no = tim(y , y , mo); if(y != mo - && y != && no == )
{
return false;
} y = no;
} if(y != )
{
return false;
} return true;
} bool MR(ll n)
{
if(n < )
return false; if(n == || n == )
return true; if((n & ) == || n % == )
return false; ll b = n - , t = ; while((b & ) == )
{
b >>= ;
t++;
} ll i, ty[] = { , , , , , , , }; for(i = ; i < ; i++)
{
if(!tes(b , t , ty[i] , n) && ty[i] < n)
{
return false;
}
} return true;
} ll Ro(ll n , ll c)
{
srand(time(NULL));
ll x0 = rand() % (n - ) + ; ll x = x0, y = x0, k = , i = , d = ; while(d == )
{
k++;
x = (tim(x , x , n) + c) % n; d = gcd(- * min(x - y , y - x) , n); if(d > && d < n)
return d; if(d == n)
return -; if(k == i)
{
y = x;
i <<= ;
}
}
} void fj(ll n)
{
if(n == )
return; if(MR(n))
{
box[num++] = n;
return;
} ll p = -, c = ; while(p == -)
p = Ro(n , c--); fj(n / p);
fj(p);
} ll fact[], common;
int cnt = ;
void dfs(ll now, int n)
{
if(now>sqrt(N)) return;
common = max(common, now); for(int i=n;i<=cnt;i++) dfs(now*fact[i], i+);
} int main()
{ ll lcm, gcd;
while(scanf("%lld %lld", &gcd, &lcm)!=EOF)
{
N = lcm / gcd; MR(N);
num = ;
fj(N); sort(box, box+num);
// for(int i=0;i<num;i++)
// printf("%lld\n", box[i]); cnt = ;
for(int i=;i<;i++) fact[i] = ;
fact[] = box[];
for(int i=;i<num;i++)
{
if(box[i]==box[i-]) fact[cnt] *= box[i];
else fact[++cnt] = box[i];
}
//for(int i=0;i<=cnt;i++) printf("%lld\n", fact[i]); common = ;
dfs(, );
printf("%lld %lld\n", common*gcd, lcm/common*gcd);
} return ;
}
END.
简单数论 | Day3 部分题解的更多相关文章
- Pairs Forming LCM (LightOJ - 1236)【简单数论】【质因数分解】【算术基本定理】(未完成)
Pairs Forming LCM (LightOJ - 1236)[简单数论][质因数分解][算术基本定理](未完成) 标签: 入门讲座题解 数论 题目描述 Find the result of t ...
- Help Hanzo (LightOJ - 1197) 【简单数论】【筛区间质数】
Help Hanzo (LightOJ - 1197) [简单数论][筛区间质数] 标签: 入门讲座题解 数论 题目描述 Amakusa, the evil spiritual leader has ...
- Aladdin and the Flying Carpet (LightOJ - 1341)【简单数论】【算术基本定理】【分解质因数】
Aladdin and the Flying Carpet (LightOJ - 1341)[简单数论][算术基本定理][分解质因数](未完成) 标签:入门讲座题解 数论 题目描述 It's said ...
- Sigma Function (LightOJ - 1336)【简单数论】【算术基本定理】【思维】
Sigma Function (LightOJ - 1336)[简单数论][算术基本定理][思维] 标签: 入门讲座题解 数论 题目描述 Sigma function is an interestin ...
- Least Common Multiple (HDU - 1019) 【简单数论】【LCM】【欧几里得辗转相除法】
Least Common Multiple (HDU - 1019) [简单数论][LCM][欧几里得辗转相除法] 标签: 入门讲座题解 数论 题目描述 The least common multip ...
- 七夕节 (HDU - 1215) 【简单数论】【找因数】
七夕节 (HDU - 1215) [简单数论][找因数] 标签: 入门讲座题解 数论 题目描述 七夕节那天,月老来到数字王国,他在城门上贴了一张告示,并且和数字王国的人们说:"你们想知道你们 ...
- Goldbach`s Conjecture(LightOJ - 1259)【简单数论】【筛法】
Goldbach`s Conjecture(LightOJ - 1259)[简单数论][筛法] 标签: 入门讲座题解 数论 题目描述 Goldbach's conjecture is one of t ...
- (step7.2.1)hdu 1395(2^x mod n = 1——简单数论)
题目大意:输入一个整数n,输出使2^x mod n = 1成立的最小值K 解题思路:简单数论 1)n可能不能为偶数.因为偶数可不可能模上偶数以后==1. 2)n肯定不可能为1 .因为任何数模上1 == ...
- 简单数论之整除&质因数分解&唯一分解定理
[整除] 若a被b整除,即a是b的倍数,那么记作b|a("|"是整除符号),读作"b整除a"或"a能被b整除".b叫做a的约数(或因数),a ...
随机推荐
- Web前端开发必备手册(Cheat sheet)
转自:http://blog.bingo929.com/cheat-sheets-for-web-develop.html Cheat sheet这个词组如果直译成中文,意思大概是”作弊小抄”之类的词 ...
- java_函数式编程写法
package cn.aikang.Test; import org.junit.Test; import java.util.Scanner; import java.util.function.S ...
- Worker Thread等到工作来,来了就工作
Worker是“工人”的意思,worker thread pattern中,工人线程(worker thread)会一次抓一件工作来处理,当没有工作可做时,工人线程会停下来等待心得工作过来. Work ...
- 期望dp+高斯消元+bfs——hdu4418
高斯消元又弄了半天.. 注意只要能建立矩阵,那就必定有解,所以高斯消元里可以直接return 1 #include<bits/stdc++.h> using namespace std; ...
- VC中隐藏和显示IDC_STATIC
void CImageShowAndHideDlg::OnBnClickedButton1() //隐藏 { CWnd* pWnd = GetDlgItem(IDC_STATIC); ...
- SQLServer日期格式化及创建相关日期
DECLARE @FirstDay_M DATETIME --本月初日期 ,); DECLARE @LastDay_M DATETIME --本月末日期 SET @LastDay_M = DATEAD ...
- [VS2008] Debug版本程序发布后 由于应用程序的配置不正确,应用程序未能启动,重新安装应用程序可能会纠正这个问题
转自VC错误:http://www.vcerror.com/?p=59 问题描述: [VS2008] 版本程序发布后,运行程序弹出错误框: 由于应用程序的配置不正确,应用程序未能启动,重新安装应用程序 ...
- HDFS under replicated blocks
under replicated blocks 解决: 找出没有复制的block: hdfs fsck / | grep 'Under replicated' | awk -F':' '{print ...
- 4_7.springboot2.x嵌入式servlet容器自动配置原理
概述 Spring Boot对所支持的Servlet Web服务器实现做了建模抽象: Servlet容器类型 WebServer模型接口 WebServer工厂实现类 Tomcat Tomca ...
- WebClient 上传文件 上传文件到服务器端
一直对于上传文件到服务器端困惑:以前,现在,学到了关于WebClient的post知识 瞬间对于上传文件到服务器觉得好轻松: 原理很简单:我们通过post服务器的页面:把本地的文件直接传递过去: 现在 ...