HDU 6706 杜教筛

HDU 6706 杜教筛


传送门: http://acm.hdu.edu.cn/showproblem.php?pid=6706

题意

求 解 ∑ i = 1 n ∑ j = 1 i g c d ( i a − j a , i b − j b ) [ g c d ( i , j ) = 1 ] 求解\sum_{i=1}^n\sum_{j=1}^igcd(i^a-j^a,i^b-j^b)[gcd(i,j)=1] i=1nj=1igcd(iaja,ibjb)[gcd(i,j)=1]

思路

g c d ( i a − j a , i b − j b ) = i g c d ( a , b ) − j g c d ( a , b ) gcd(i^a-j^a,i^b-j^b)=i^{gcd(a,b)}-j^{gcd(a,b)} gcd(iaja,ibjb)=igcd(a,b)jgcd(a,b)

题 目 说 g c d ( a , b ) = 1 , 所 以 那 个 复 杂 的 式 子 直 接 变 成 i − j . 题目说gcd(a,b)=1,所以那个复杂的式子直接变成i-j. gcd(a,b)=1ij.

∑ i = 1 n ∑ j = 1 i ( i − j ) [ g c d ( i , j ) = 1 ] \sum_{i=1}^n\sum_{j=1}^i(i-j)[gcd(i,j)=1] i=1nj=1i(ij)[gcd(i,j)=1]

∑ i = 1 n ∑ j = 1 i i [ g c d ( i , j ) = 1 ] − ∑ i = 1 n ∑ j = 1 i j [ g c d ( i , j ) = 1 ] \sum_{i=1}^n\sum_{j=1}^ii[gcd(i,j)=1]-\sum_{i=1}^n\sum_{j=1}^ij[gcd(i,j)=1] i=1nj=1ii[gcd(i,j)=1]i=1nj=1ij[gcd(i,j)=1]

左 边 为 与 i 互 质 的 个 数 , 右 边 为 比 i 小 并 且 互 质 的 数 字 和 , 即 为 : 左边为与i互质的个数,右边为比i小并且互质的数字和,即为: ii

∑ i = 1 n i φ ( i ) − ∑ i = 1 n i φ ( i ) + 1 2 \sum_{i=1}^ni\varphi (i)-\frac{\sum_{i=1}^ni\varphi (i)+1}{2} i=1niφ(i)2i=1niφ(i)+1

∑ i = 1 n i φ ( i ) − 1 2 \frac{\sum_{i=1}^ni\varphi (i)-1}{2} 2i=1niφ(i)1

因 为 n 有 1 e 9 , 所 以 需 要 杜 教 筛 优 化 。 因为n有1e9,所以需要杜教筛优化。 n1e9

f ∗ g ( n ) = ∑ d ∣ n f ( d ) g ( n d ) = ∑ d ∣ n i d ( d ) ∗ φ ( d ) ∗ g ( n d ) f*g(n)=\sum_{d|n}f(d)g(\frac{n}{d})=\sum_{d|n}id(d)*\varphi (d)*g(\frac{n}{d}) fg(n)=dnf(d)g(dn)=dnid(d)φ(d)g(dn)

很 显 然 , 设 g = i d , 则 : 很显然,设g=id,则: g=id

f ∗ g ( n ) = ∑ d ∣ n φ ( d ) i d ( n ) = n ∑ d ∣ n φ ( d ) = i d ( n ) ( φ ∗ I ) = i d 2 ( n ) = n 2 f*g(n)=\sum_{d|n}\varphi (d)id(n)=n\sum_{d|n}\varphi (d)=id(n)(\varphi *I)=id^2(n)=n^2 fg(n)=dnφ(d)id(n)=ndnφ(d)=id(n)(φI)=id2(n)=n2

所 以 得 : S ( n ) = ∑ i = 1 n ( f ∗ g ) i − ∑ i = 2 n g ( i ) S ( n i ) = n ( n + 1 ) ( 2 n + 1 ) 6 − ∑ i = 2 n i S ( n i ) 所以得:S(n)=\sum_{i=1}^n(f*g)i-\sum_{i=2}^ng(i)S(\frac{n}{i})=\frac{n(n+1)(2n+1)}{6}-\sum_{i=2}^niS(\frac{n}{i}) S(n)=i=1n(fg)ii=2ng(i)S(in)=6n(n+1)(2n+1)i=2niS(in)

Code

#include "bits/stdc++.h"
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef pair<double, double> pdd;
typedef pair<ll, ll> pll;

#define endl "\n"
#define eb emplace_back
#define mem(a, b) memset(a , b , sizeof(a))

const ll INF = 0x3f3f3f3f;
// const ll mod = 998244353;
const ll mod = 1e9 + 7;
const double eps = 1e-6;
const double PI = acos(-1);
const double R = 0.57721566490153286060651209;

template<typename T>
inline void read(T &a) {char c = getchar();T x = 0, f = 1;
    while (!isdigit(c)) {if (c == '-')f = -1;c = getchar();}
    while (isdigit(c)) {x = (x << 1) + (x << 3) + c - '0';c = getchar();}a = f * x;
}

const int N = 1e6 + 10;

bool is_prime[N];
int prime[N], cnt;
int phi[N];
ll sum_i_phi[N];

void init() {
    phi[1] = 1;
    for(int i = 2;i < N; i++) {
        if(!is_prime[i]) prime[++cnt] = i, phi[i] = i - 1;
        for(int j = 1;j <= cnt && i * prime[j] < N; j++) {
            is_prime[i * prime[j]] = 1;
            if(i % prime[j] == 0) {
                phi[i * prime[j]] = phi[i] * prime[j];
                break;
            }
            else phi[i * prime[j]] = phi[i] * phi[prime[j]];
        }
    }
    for(int i = 1;i < N; i++) {
        sum_i_phi[i] = (sum_i_phi[i - 1] + 1ll * i * phi[i] % mod) % mod;
    }
}

ll quick_pow(ll a, ll b) {
    ll ans = 1;
    while(b) {
        if(b & 1) ans = ans * a % mod;
         a = a * a % mod;
         b >>= 1;
    }
    return ans % mod;
}

ll inv2;
ll inv6;

map<ll, ll> mp;

ll S(ll x) {
    if(x < N) return sum_i_phi[x];
    else if(mp[x]) return mp[x];
    ll ans = x * (x + 1) % mod * (2 * x + 1) % mod * inv6 % mod;
    for(int l = 2, r;l <= x; l = r + 1) {
        r = min(x, x / (x / l));
        ans = (ans - 1ll * (r + l) % mod * (r - l + 1) % mod * inv2 % mod * S(x / l)) % mod;
    }
    return mp[x] = ans;
}

void solve() {
    init();
    inv2 = quick_pow(2, mod - 2);
    inv6 = quick_pow(6, mod - 2);
    int _; scanf("%d",&_);
    while(_--) {
        ll n, a, b; scanf("%lld%lld%lld",&n,&a,&b);
        ll ans = (S(n) - 1) % mod;
        ans = ans * inv2 % mod;
        printf("%lld\n",(ans % mod + mod) % mod);
    }
}

signed main() {
    ios_base::sync_with_stdio(false);
    // cin.tie(nullptr);
    // cout.tie(nullptr);
#ifdef FZT_ACM_LOCAL
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    signed test_index_for_debug = 1;
    char acm_local_for_debug = 0;
    do {
        if (acm_local_for_debug == '$') exit(0);
        if (test_index_for_debug > 20)
            throw runtime_error("Check the stdin!!!");
        auto start_clock_for_debug = clock();
        solve();
        auto end_clock_for_debug = clock();
        cout << "Test " << test_index_for_debug << " successful" << endl;
        cerr << "Test " << test_index_for_debug++ << " Run Time: "
             << double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
        cout << "--------------------------------------------------" << endl;
    } while (cin >> acm_local_for_debug && cin.putback(acm_local_for_debug));
#else
    solve();
#endif
    return 0;
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值