HDU5780 gcd 欧拉函数

http://acm.hdu.edu.cn/showproblem.php?pid=5780

BC #85 1005

思路:

首先原式化简:x?^gcd(a,b)??−1

也就是求n内,(公约数是i的对数)*x^i-1的和,其中i为n内的两两最大公约数。那么问题可以转化成先预处理出i,再求和,注意O(n*300)=1,正常情况会卡常数。必须还要优化

由于 ans=∑s[d]∗(x^?d??−1),记s[d]=最大公约数为d的对数

我们注意到求s[d] or (公约数是i的对数),也就是求n/i以内互质数的对数,显然用欧拉来做

s[d]=2*(phi[1]+phi[2]+...+phi[n/d])-1

注意到:d不同,但是n/d一样,也就是s[d]可能有多个相同,比如 10/6 10/7 10/8 10/9 10/10,所以求s[d]相同的项,我们可以用等比公式求和(快速幂+逆元 新知识)

所以我们只要找到每一段s[d]就可以 即 j=n/(n/i),j为最后一个相同s[d]的下标

 1 // #pragma comment(linker, "/STACK:102c000000,102c000000")
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <sstream>
 6 #include <string>
 7 #include <algorithm>
 8 #include <list>
 9 #include <map>
10 #include <vector>
11 #include <queue>
12 #include <stack>
13 #include <cmath>
14 #include <cstdlib>
15 // #include <conio.h>
16 using namespace std;
17 #define pi acos(-1.0)
18 const int N = 1e6+10;
19 const int MOD = 1e9+7;
20 #define inf 0x7fffffff
21 typedef long long  LL;
22
23 void fre() { freopen("in.txt","r",stdin);}
24 inline int read(){int x=0,f=1;char ch=getchar();while(ch>‘9‘||ch<‘0‘) {if(ch==‘-‘) f=-1;ch=getchar();}while(ch>=‘0‘&&ch<=‘9‘) { x=x*10+ch-‘0‘;ch=getchar();}return x*f;}
25
26 LL pow_m(LL x,LL n)
27 {
28     LL res=1;
29     while(n>0)
30     {
31         if(n & 1)
32             res=(res*x)%MOD;
33         x=(x*x)%MOD;
34         n >>= 1;
35     }
36     return res;
37 }
38
39 int prime[N],sphi[N];
40 int inv[N];
41 void e_fun(){
42     sphi[1]=1;
43     for(int i=2;i<=N;i++){
44         if(!sphi[i]){
45             prime[++prime[0]]=i;
46             sphi[i]=i-1;
47         }
48         for(int j=1;j<=prime[0]&&i*prime[j]<=N;j++){
49             if(i%prime[j]) sphi[i*prime[j]]=sphi[i]*(prime[j]-1);
50             else sphi[i*prime[j]]=sphi[i]*prime[j];
51         }
52     }
53     for(int i=1;i<=N;i++) sphi[i]=(sphi[i-1]+sphi[i])%MOD;
54
55     //打表求逆元
56     // inv[1] = inv[0] = 1;
57     // for(int i = 2;i < N;i++)
58     // inv[i] = inv[MOD%i]*(MOD-MOD/i)%MOD;
59 }
60
61
62 void ex_gcd(LL a,LL b,LL &d,LL &x,LL &y) {
63     if (!b) {
64         d = a;
65         x = 1;
66         y = 0;
67     }
68     else {
69         ex_gcd(b, a%b, d, y, x);
70         y -= x*(a/b);
71     }
72     // return x;
73 }
74
75 LL sn(LL q,LL n){
76     if(q==1) return n;
77     LL x,y,d;
78     ex_gcd(q-1,MOD,d,x,y);
79     return (pow_m(q,n)-1)*((x+MOD)%MOD)%MOD;
80 }
81
82 int main(){
83     e_fun();
84     int T;
85     T=read();
86     while(T--){
87         int x,n;
88         x=read(),n=read();
89         LL ans=0;
90         for(int i=1,j;i<=n;i=j+1){
91             j=n/(n/i);
92             LL sd=2*sphi[n/i]-1;
93             ans=(ans + sd*(pow_m(x,i)*sn(x,j-i+1)%MOD -(j-i+1))%MOD) % MOD;
94         }
95         printf("%I64d\n",ans);
96     }
97     return 0;
98 }
时间: 2024-10-13 13:53:45

HDU5780 gcd 欧拉函数的相关文章

HDU 1695 GCD 欧拉函数+容斥原理+质因数分解

链接:http://acm.hdu.edu.cn/showproblem.php?pid=1695 题意:在[a,b]中的x,在[c,d]中的y,求x与y的最大公约数为k的组合有多少.(a=1, a <= b <= 100000, c=1, c <= d <= 100000, 0 <= k <= 100000) 思路:因为x与y的最大公约数为k,所以xx=x/k与yy=y/k一定互质.要从a/k和b/k之中选择互质的数,枚举1~b/k,当选择的yy小于等于a/k时,可以

HDU 2588 GCD (欧拉函数)

GCD Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1013    Accepted Submission(s): 457 Problem Description The greatest common divisor GCD(a,b) of two positive integers a and b,sometimes writt

hdu 1695 GCD 欧拉函数+容斥

题意:给定a,b,c,d,k x属于[1 , c],y属于[1 , d],求满足gcd(x,y)=k的对数.其中<x,y>和<y,x>算相同. 思路:不妨设c<d,x<=y.问题可以转化为x属于[1,c / k ],y属于[1,d/k ],x和y互质的对数. 那么假如y<=c/k,那么对数就是y从1到c/k欧拉函数的和.如果y>c/k,就只能从[ c/k+1 , d ]枚举,然后利用容斥.详见代码: /****************************

hdu2588 gcd 欧拉函数

GCD Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1567    Accepted Submission(s): 751 Problem Description The greatest common divisor GCD(a,b) of two positive integers a and b,sometimes writte

hdu 1695 GCD(欧拉函数+容斥原理)

http://acm.hdu.edu.cn/showproblem.php? pid=1695 非常经典的题.同一时候感觉也非常难. 在区间[a,b]和[c,d]内分别随意取出一个数x,y,使得gcd(x,y) = k.问这种(x,y)有多少对.能够觉得a,c均为1,并且gcd(5,7)与gcd(7,5)是同一种. 由于gcd(x,y) = k,那么gcd(x/k,y/k) = 1.也就是求区间[1,b/k]和[1,d/k]内这种(x,y)对使得gcd(x,y) = 1. 为了防止计数反复,首先

HDU 1695 GCD 欧拉函数+容斥定理

输入a b c d k求有多少对x y 使得x在a-b区间 y在c-d区间 gcd(x, y) = k 此外a和c一定是1 由于gcd(x, y) == k 将b和d都除以k 题目转化为1到b/k 和1到d/k 2个区间 如果第一个区间小于第二个区间 讲第二个区间分成2部分来做1-b/k 和 b/k+1-d/k 第一部分对于每一个数i 和他互质的数就是这个数的欧拉函数值 全部数的欧拉函数的和就是答案 第二部分能够用全部数减去不互质的数 对于一个数i 分解因子和他不互质的数包括他的若干个因子 这个

[题解](gcd/欧拉函数)luogu_P2568_GCD

求gcd(x,y)=p等价于求gcd(x/p,y/p)=1,转化为了n/p内互质的个数 所以欧拉函数,因为有序所以乘2,再特判一下只有在1,1情况下才会重复计算,所以每次都减一 数组开小一时爽,提交wa火葬场!!! #include<iostream> #include<cstdio> #include<cstring> using namespace std; const int maxn=10000009; int n; int ck[maxn],prime[max

hdu 1695 GCD 欧拉函数 + 容斥

http://acm.hdu.edu.cn/showproblem.php?pid=1695 要求[L1, R1]和[L2, R2]中GCD是K的个数.那么只需要求[L1, R1 / K]  和 [L2, R2 / K]中GCD是1的对数. 由于(1, 2)和(2, 1)是同一对. 那么我们枚举大区间,限制数字一定是小于等于枚举的那个数字就行. 比如[1, 3]和[1, 5] 我们枚举大区间,[1, 5],在[1, 3]中找互质的时候,由于又需要要小于枚举数字,那么直接上phi 对于其他的,比如

BZOJ2818 Gcd 欧拉函数

题意:给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的数对(x,y)有多少对. 题解:我们枚举素数p,后面的过程和BZOJ2705一样,不同的是我们限制x>=y,假定得到的答案是ans,那么实际上答案是2*ans-1(加上x<=y,x==y重复计算了) #include <cmath> #include <cstring> #include <cstdlib> #include <iostream> #include <