HDU 5780 gcd

来源:互联网 发布:藏剑正太捏脸数据 编辑:程序博客网 时间:2024/05/21 16:59
Problem Description
Little White learned the greatest common divisor, so she plan to solve a problem: given x, n,
query ∑gcd(xa1,xb1) (1a,bn)
 

Input
The first line of input is an integer T ( 1T300)
For each test case ,the single line contains two integers x and n ( 1x,n1000000)
 

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

Sample Input
53 14 28 710 510 8
 

Sample Output
2242398375111465111134466

可以猜到,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 0
原创粉丝点击