HYSBZ 3512 (BZOJ 3512) DZY Loves Math IV

题目: 求 ∑ i = 1 n ∑ j = 1 m φ ( i ∗ j ) \sum_{i = 1}^n\sum_{j = 1} ^ m \varphi(i * j) i=1nj=1mφ(ij)
解法:

  1. 我们发现 n n n很小 ,于是考虑枚举 i i i, 于是对于每个 i i i只需要求 ∑ j = 1 m φ ( i ∗ j ) \sum_{j = 1} ^ m \varphi(i * j) j=1mφ(ij)
  2. ω \omega ω i i i中所有不同的素因子的乘积, λ λ λ i ω \frac{i}{\omega} ωi,于是问题只需要求 λ ∑ j = 1 m φ ( ω ∗ j ) λ\sum_{j = 1} ^ m \varphi(\omega* j) λj=1mφ(ωj).
  3. S ( ω , m ) = ∑ j = 1 m φ ( ω ∗ j ) S(\omega, m) =\sum_{j = 1} ^ m \varphi(\omega* j) S(ω,m)=j=1mφ(ωj)
  4. → \rightarrow S ( ω , m ) = ∑ j = 1 m ( φ ( ω ) φ ( g c d ( ω , j ) ) ) φ ( j ) g c d ( ω , j ) S(\omega, m) =\sum_{j = 1} ^ m (\frac{\varphi(\omega)}{\varphi(gcd(\omega, j))})\varphi(j)gcd(\omega, j) S(ω,m)=j=1m(φ(gcd(ω,j))φ(ω))φ(j)gcd(ω,j)
  5. → \rightarrow S ( ω , m ) = ∑ j = 1 m φ ( ω g c d ( ω , j ) ) φ ( j ) g c d ( ω , j ) S(\omega, m) =\sum_{j = 1} ^ m \varphi(\frac{\omega}{gcd(\omega, j)})\varphi(j)gcd(\omega, j) S(ω,m)=j=1mφ(gcd(ω,j)ω)φ(j)gcd(ω,j)
  6. → \rightarrow S ( ω , m ) = ∑ j = 1 m φ ( ω g c d ( ω , j ) ) φ ( j ) ∑ d ∣ g c d ( ω , j ) φ ( d ) S(\omega, m) =\sum_{j = 1} ^ m \varphi(\frac{\omega}{gcd(\omega, j)})\varphi(j)\sum_{d|gcd(\omega, j)}\varphi(d) S(ω,m)=j=1mφ(gcd(ω,j)ω)φ(j)dgcd(ω,j)φ(d)
  7. → \rightarrow S ( ω , m ) = ∑ j = 1 m φ ( j ) ∑ d ∣ g c d ( ω , j ) φ ( d ) φ ( ω g c d ( ω , j ) ) S(\omega, m) =\sum_{j = 1} ^ m\varphi(j)\sum_{d|gcd(\omega, j)}\varphi(d)\varphi(\frac{\omega}{gcd(\omega, j)}) S(ω,m)=j=1mφ(j)dgcd(ω,j)φ(d)φ(gcd(ω,j)ω)
  8. → \rightarrow S ( ω , m ) = ∑ j = 1 m φ ( j ) ∑ d ∣ g c d ( ω , j ) φ ( ω d ) S(\omega, m) =\sum_{j = 1} ^ m\varphi(j)\sum_{d|gcd(\omega, j)} \varphi(\frac{\omega}{d}) S(ω,m)=j=1mφ(j)dgcd(ω,j)φ(dω)
  9. → \rightarrow S ( ω , m ) = ∑ d ∣ ω φ ( ω d ) ∑ j = 1 ⌊ m d ⌋ φ ( j ∗ d ) S(\omega, m) =\sum_{d|\omega}\varphi(\frac{\omega}{d})\sum_{j = 1}^{\lfloor \frac{m}{d} \rfloor}\varphi(j*d) S(ω,m)=dωφ(dω)j=1dmφ(jd)
  10. → \rightarrow S ( ω , m ) = ∑ d ∣ ω φ ( ω d ) S ( d , ⌊ m d ⌋ ) S(\omega, m) =\sum_{d|\omega}\varphi(\frac{\omega}{d})S(d,\lfloor \frac{m}{d}\rfloor) S(ω,m)=dωφ(dω)S(d,dm)
  11. ω = 1 \omega=1 ω=1时杜教筛求 ∑ i = 1 m φ ( i ) \sum_{i=1}^{m}\varphi(i) i=1mφ(i)
  12. O ( 能 过 ) O(能过) O()

代码:

 /**************************************************************
    Problem: 3512
    User: Ransln
    Language: C++
    Result: Accepted
    Time:6100 ms
    Memory:27852 kb
****************************************************************/
 
#include <bits/stdc++.h>
#define ll long long
using namespace std;
 
const int Max = 1e6 + 100;
const int MOD = 1e9 + 7;
int prime[Max], tot, phi[Max], sum[Max];
bool vis[Max];
void init(){
    phi[1] = 1;
    for(int i = 2; i < Max; i++){
        if(!vis[i])prime[tot ++] = i, phi[i] = i - 1;
        for(int j = 0; j < tot; j++){
            int tmp = i * prime[j];
            if(tmp >= Max)break;
            vis[tmp] = true;
            if(i % prime[j] == 0){
                phi[tmp] = phi[i] * prime[j];
                break;
            }
            phi[tmp] = phi[i] * (prime[j] - 1);
        }
    }
    for(int i = 1; i < Max; i++)sum[i] = (sum[i - 1] + phi[i]) % MOD;
}
vector<int> divide(ll x){
    vector<int> now;
    for(int i = 0; i < tot; i++){
        if(prime[i] * prime[i] > x)break;
        if(x % prime[i] == 0){
            now.push_back(prime[i]);
            while(x % prime[i] == 0)x /= prime[i];
        }
    }
    if(x != 1)now.push_back((int)x);
    return now;
}
map<ll, ll> Hash;
map<ll, ll> M;
ll solve(ll m){
    if(m < Max)return sum[m];
    if(Hash.count(m))return Hash[m];
    ll ans = 0;
    for(ll i = 2, j; i <= m; i = j + 1){
        j = m / (m / i);
        ans = (ans + (j - i + 1) * solve(m / i) % MOD) % MOD;
    }
    ans = (((((1 + m) * m) / 2) % MOD) - ans + MOD)% MOD;
    return Hash[m] = ans;
}
ll S(ll n, ll m){
    if(m == 1)return phi[n];
    if(n == 1)return solve(m);
    if(m == 0)return 0;
    if(M.count(n * (ll)1e10 + m))return M[n * (ll)1e10 + m];
    vector<int> p = divide(n);
    int len = p.size();
    ll ans = 0;
    for(int i = 0; i < (1 << len); i++){
        ll tmp = 1;
        for(int j = 0; j < len; j++){
            if(i >> j & 1)tmp = tmp * p[j];
        }
        ans = (ans + phi[n / tmp] * S(tmp, m / tmp)) % MOD;
    }
    return M[n * (ll)1e10 + m] = ans;
}
int main(){
    ll n, m;init();
    scanf("%lld%lld", &n, &m);
    ll ans = 0;
    for(int i = 1; i <= n; i++){
        vector<int> p = divide(i);
        int len = p.size(), x = 1;
        for(int j = 0; j < len; j++) x = x * p[j];
        ans = (ans + i / x * S(x, m)) % MOD;
    }
    printf("%lld\n", ans);
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值