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
",ans);
96     }
97     return 0;
98 }
原文地址:https://www.cnblogs.com/ITUPC/p/5725041.html