0
点赞
收藏
分享

微信扫一扫

HDU 5780 gcd


Problem Description


Little White learned the greatest common divisor, so she plan to solve a problem: given x, n,
query ∑gcd( xa−1, xb−1) ( 1≤a,b≤n)


 



Input


1≤T≤300)
For each test case ,the single line contains two integers x and n (  1≤x,n≤1000000)


 



Output


For each testcase, output a line, the answer mod 1000000007


 



Sample Input


5 3 1 4 2 8 7 10 5 10 8


 



Sample Output


2 24 2398375 111465 111134466


可以猜到,gcd(x^a-1,x^b-1)=x^gcd(a,b)-1

所以原式便成为了求1<=a,b<=n的各个gcd的值了。

可以先用欧拉函数预处理出n里面互质的对数。

然后暴力枚举gcd=i的有几对,就相当于求n/i里面有几对互质

乘上x^i即可,-1的话,因为每一对都有,所以可以提出来,最后减个n*n就好了。

但是T很多,暴力枚举i会超时,可以知道,n/i是下降的,并且有一段连续的,

所以可以分段处理,然后同时log去计算一段的x^i的和即可。

#include<set>
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<bitset>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
#define rep(i,j,k) for (int i = j; i <= k; i++)
#define per(i,j,k) for (int i = j; i >= k; i--)
using namespace std;
typedef __int64 LL;
const int low(int x) { return x&-x; }
const double eps = 1e-8;
const int INF = 0x7FFFFFFF;
const int mod = 1e9 + 7;
const int N = 1e6 + 10;
int T, n, m, ans, q, t;
int p[N], phi[N], f[N], s[N];
int g[N], ss[N];
int G[N], SS[N];

void get_prime()
{
t = 0;
rep(i, 2, N - 1)
{
if (!f[i]) p[t++] = i, phi[i] = i - 1;
for (int j = 0; j < t&&i*p[j] < N; j++)
{
f[i*p[j]] = 1;
if (i%p[j] == 0) {
phi[i*p[j]] = phi[i] * p[j];
break;
}
else phi[i*p[j]] = phi[i] * (p[j] - 1);
}
}
t = s[0] = 0;
rep(i, 1, N - 1) s[i] = (s[i - 1] + phi[i]) % mod;
rep(i, 1, N - 1) s[i] = (s[i] << 1 | 1) % mod;
}

int get_g(int x)
{
if (G[x] == t) return g[x];
g[x] = get_g(x >> 1);
g[x] = 1LL * g[x] * g[x] % mod;
if (x & 1) g[x] = 1LL * g[x] * m%mod;
G[x] = t; return g[x];
}

int get_s(int x)
{
if (SS[x] == t) return ss[x];
if (x & 1)
{
ss[x] = get_s(x >> 1);
ss[x] = (1LL * ss[x] * get_g((x >> 1) + 1) + ss[x]) % mod;
}
else
{
ss[x] = get_s((x >> 1) - 1);
ss[x] = (1LL * ss[x] * get_g((x >> 1) + 1) + ss[x] + get_g(x >> 1)) % mod;
}
SS[x] = t; return ss[x];
}

int main()
{
get_prime();
scanf("%d", &T);
while (T--)
{
++t;
G[0] = SS[0] = t;
g[0] = ss[0] = 1;
scanf("%d%d", &m, &n);
ans = 0; q = m;
for (int i = 1, j, k; i <= n; i = k + 1)
{
j = n / i; k = n / j;
ans = (1LL * s[j] * (1LL * q * get_s(k - i) % mod) + ans) % mod;
q = 1LL * q * get_g(k - i + 1) % mod;
}
ans = ((-1LL * n*n + ans) % mod + mod) % mod;
printf("%d\n", ans);
}
return 0;
}



举报

相关推荐

0 条评论