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 部分题解的更多相关文章

  1. Pairs Forming LCM (LightOJ - 1236)【简单数论】【质因数分解】【算术基本定理】(未完成)

    Pairs Forming LCM (LightOJ - 1236)[简单数论][质因数分解][算术基本定理](未完成) 标签: 入门讲座题解 数论 题目描述 Find the result of t ...

  2. Help Hanzo (LightOJ - 1197) 【简单数论】【筛区间质数】

    Help Hanzo (LightOJ - 1197) [简单数论][筛区间质数] 标签: 入门讲座题解 数论 题目描述 Amakusa, the evil spiritual leader has ...

  3. Aladdin and the Flying Carpet (LightOJ - 1341)【简单数论】【算术基本定理】【分解质因数】

    Aladdin and the Flying Carpet (LightOJ - 1341)[简单数论][算术基本定理][分解质因数](未完成) 标签:入门讲座题解 数论 题目描述 It's said ...

  4. Sigma Function (LightOJ - 1336)【简单数论】【算术基本定理】【思维】

    Sigma Function (LightOJ - 1336)[简单数论][算术基本定理][思维] 标签: 入门讲座题解 数论 题目描述 Sigma function is an interestin ...

  5. Least Common Multiple (HDU - 1019) 【简单数论】【LCM】【欧几里得辗转相除法】

    Least Common Multiple (HDU - 1019) [简单数论][LCM][欧几里得辗转相除法] 标签: 入门讲座题解 数论 题目描述 The least common multip ...

  6. 七夕节 (HDU - 1215) 【简单数论】【找因数】

    七夕节 (HDU - 1215) [简单数论][找因数] 标签: 入门讲座题解 数论 题目描述 七夕节那天,月老来到数字王国,他在城门上贴了一张告示,并且和数字王国的人们说:"你们想知道你们 ...

  7. Goldbach`s Conjecture(LightOJ - 1259)【简单数论】【筛法】

    Goldbach`s Conjecture(LightOJ - 1259)[简单数论][筛法] 标签: 入门讲座题解 数论 题目描述 Goldbach's conjecture is one of t ...

  8. (step7.2.1)hdu 1395(2^x mod n = 1——简单数论)

    题目大意:输入一个整数n,输出使2^x mod n = 1成立的最小值K 解题思路:简单数论 1)n可能不能为偶数.因为偶数可不可能模上偶数以后==1. 2)n肯定不可能为1 .因为任何数模上1 == ...

  9. 简单数论之整除&质因数分解&唯一分解定理

    [整除] 若a被b整除,即a是b的倍数,那么记作b|a("|"是整除符号),读作"b整除a"或"a能被b整除".b叫做a的约数(或因数),a ...

随机推荐

  1. NEO4J亿级数据全文索引构建优化

    NEO4J亿级数据全文索引构建优化 一.数据量规模(亿级) 二.构建索引的方式 三.构建索引发生的异常 四.全文索引代码优化 1.Java.lang.OutOfMemoryError 2.访问数据库时 ...

  2. 在Logstash的配置文件中对日志事件进行区分

    1.多个日志文件作为输入源 input { # 通过给日志事件定义类型来区分 file { path => ["/var/log/nginx/access.log"] typ ...

  3. java编程——数据的加法

    设计思想: 第一步:从键盘上输入一定个数的整数. 第二步:因为在main()方法中的参数是String类型的,所以第一步中输入的其实是字符类型,在这一步要把String转化成int. 第三步:初始化s ...

  4. 2019-7-27-解决从旧格式的-csproj-迁移到新格式的-csproj-格式-AssemblyInfo-文件值重复问题...

    title author date CreateTime categories 解决从旧格式的 csproj 迁移到新格式的 csproj 格式 AssemblyInfo 文件值重复问题 lindex ...

  5. SQL语句转换成MapReduce的基本原理

  6. css---盒模型新增样式

    box-shadow 以逗号分割列表来描述一个或多个阴影效果,可以用到几乎任何元素上. 如果元素同时设置了 border-radius ,阴影也会有圆角效果.多个阴影时和多个 text shadows ...

  7. 校园商铺-2项目设计和框架搭建-7验证Dao

    以最简单的地区表为例 1.插入数据 insert into tb_area (area_name, priority) values('东苑', 1),('南苑', 7),('北苑', 5); sel ...

  8. Windows 10 连接服务器

    { windows + r    input mstsc } { //mstsc D:\TOOL\Servers.rdp /v 127.0.0.1:9998 }

  9. 计数dp+概率+大数——(抽屉问题解的个数)zoj3380

    难的地方在于计数dp..给定范围[1,n]的数去填m个位置,要求不能出现超过I个相同的数, 那就用dp[i][j]表示在阶段i,已经填了j个位置的可能解法,那么只要枚举i填的位置数k∈[0,min(j ...

  10. linux安装splunk-enterprise

    一.介绍 Splunk是一款功能强大,功能强大且完全集成的软件,用于实时企业日志管理,可收集,存储,搜索,诊断和报告任何日志和机器生成的数据,包括结构化,非结构化和复杂的多行应用程序日志. 它允许您以 ...