• bzoj3994 [SDOI2015]约数个数和


    3994: [SDOI2015]约数个数和

    Time Limit: 20 Sec  Memory Limit: 128 MB
    Submit: 1125  Solved: 780
    [Submit][Status][Discuss]

    Description

     设d(x)为x的约数个数,给定N、M,求  
     

     

    Input

    输入文件包含多组测试数据。

    第一行,一个整数T,表示测试数据的组数。
    接下来的T行,每行两个整数N、M。
     

    Output

     T行,每行一个整数,表示你所求的答案。

     

    Sample Input

    2
    7 4
    5 6

    Sample Output

    110
    121

    HINT

     1<=N, M<=50000


    1<=T<=50000

    Source

    Round 1 感谢yts1999上传

    分析:详见:传送门

       提一点:为什么从上面那个式子变到下面i 就变成了 id,j就变成了jd呢? 

       因为第一个式子枚举的d是gcd(i,j)的因数,那么i和j必然是d的倍数.为了保证答案的合法性,必须要变成这样.

       记住一点:等价于 .

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    typedef long long ll;
    
    ll prime[50010], vis[50010], tot, sum[50010], mo[50010], f[50010], T, n, m;
    
    void init()
    {
        mo[1] = 1;
        for (ll i = 2; i <= 50000; i++)
        {
            if (!vis[i])
            {
                prime[++tot] = i;
                mo[i] = -1;
            }
            for (ll j = 1; j <= tot; j++)
            {
                ll t = prime[j] * i;
                if (t > 50000)
                    break;
                vis[t] = 1;
                if (i % prime[j] == 0)
                {
                    mo[t] = 0;
                    break;
                }
                mo[t] = -mo[i];
            }
        }
        for (ll i = 1; i <= 50000; i++)
            sum[i] = sum[i - 1] + mo[i];
    }
    
    void gen(ll x)
    {
        ll res = 0, last = 0;
        for (ll i = 1; i <= x; i = last + 1)
        {
            last = x / (x / i);
            res += (last - i + 1) * (x / i);
        }
        f[x] = res;
    }
    
    ll solve()
    {
        ll res = 0, last = 0;
        for (ll i = 1; i <= min(n, m); i = last + 1)
        {
            last = min(n / (n / i), m / (m / i));
            res += (sum[last] - sum[i - 1]) * f[n / i] * f[m / i];
        }
        return res;
    }
    
    int main()
    {
        init();
        for (ll i = 1; i <= 50000; i++)
            gen(i);
        scanf("%lld", &T);
        while (T--)
        {
            scanf("%lld%lld", &n, &m);
            printf("%lld
    ", solve());
        }
        
        return 0;
    }
  • 相关阅读:
    【Linux】VMware及VirtualBox网络配置
    【Linux】VirtualBox安装ubuntu排错LowGraphic
    【Hadoop】Win7上搭建Hadoop开发环境,方法一
    【JAVA】配置JAVA环境变量,安装Eclipse
    Eureka自我保护机制
    zookeeper代替eureka作为SpringCloud的服务注册中心
    mybatisplus代码生成器
    条件构造器 EntityWrapper (重要)
    idea 常用快捷键
    MybatisPlus的通用 CRUD
  • 原文地址:https://www.cnblogs.com/zbtrs/p/7944638.html
Copyright © 2020-2023  润新知