zoukankan      html  css  js  c++  java
  • Crash的数字表格(bzoj 2054)

    Description

    今天的数学课上,Crash小朋友学习了最小公倍数(Least Common Multiple)。对于两个正整数a和b,LCM(a, b)表示能同时被a和b整除的最小正整数。例如,LCM(6, 8) = 24。回到家后,Crash还在想着课上学的东西,为了研究最小公倍数,他画了一张N*M的表格。每个格子里写了一个数字,其中第i行第j列的那个格子里写着数为LCM(i, j)。一个4*5的表格如下: 1 2 3 4 5 2 2 6 4 10 3 6 3 12 15 4 4 12 4 20 看着这个表格,Crash想到了很多可以思考的问题。不过他最想解决的问题却是一个十分简单的问题:这个表格中所有数的和是多少。当N和M很大时,Crash就束手无策了,因此他找到了聪明的你用程序帮他解决这个问题。由于最终结果可能会很大,Crash只想知道表格里所有数的和mod 20101009的值。

    Input

    输入的第一行包含两个正整数,分别表示N和M。

    Output

    输出一个正整数,表示表格中所有数的和mod 20101009的值。

    Sample Input

    4 5

    Sample Output

    122
    【数据规模和约定】
    100%的数据满足N, M ≤ 10^7。
    /*
        证明见PoPoQQQ课件:
        https://wenku.baidu.com/view/fbec9c63ba1aa8114431d9ac.html?from=search 
    */
    #include<cstdio>
    #include<iostream>
    #define N 10000010
    #define mod 20101009
    #define lon long long
    using namespace std;
    int mu[N],prime[N],mark[N],num,n,m;
    lon sum[N];
    void get_prime(){
        mu[1]=1;
        for(int i=2;i<=n;i++){
            if(!mark[i]) prime[++num]=i,mu[i]=-1;
            for(int j=1;j<=num&&i*prime[j]<=n;j++){
                mark[i*prime[j]]=1;
                mu[i*prime[j]]=-mu[i];
                if(i%prime[j]==0){
                    mu[i*prime[j]]=0;
                    break;
                }
            }
        }
        for(int i=1;i<=n;i++) sum[i]=(sum[i-1]+(1LL*mu[i]*i%mod*i%mod))%mod;
    }
    lon getsum(lon x,lon y){
        x=(x*(x+1)/2)%mod;
        y=(y*(y+1)/2)%mod;
        return x*y%mod;
    }
    lon getf(int x,int y){
        int pos;lon ans=0;
        for(int i=1;i<=min(x,y);i=pos+1){
            pos=min(x/(x/i),y/(y/i));
            ans=(ans+(sum[pos]-sum[i-1]+mod)%mod*getsum((lon)x/i,(lon)y/i)%mod)%mod;
        }
        return ans;
    }
    int main(){
        scanf("%d%d",&n,&m);
        if(n>m) swap(n,m);
        get_prime();
        int pos;lon ans=0;
        for(int i=1;i<=n;i=pos+1){
            pos=min(n/(n/i),m/(m/i));
            ans=(ans+1LL*(i+pos)*(pos-i+1)/2%mod*getf(n/i,m/i)%mod)%mod;
        }
        cout<<ans;
        return 0;
    }
  • 相关阅读:
    准备 FRM 考试——方法、工具与教训
    930. 和相同的二元子数组 前缀和
    1906. 查询差绝对值的最小值 前缀和
    剑指 Offer 37. 序列化二叉树 二叉树 字符串
    815. 公交路线 BFS
    518. 零钱兑换 II dp 完全背包
    1049. 最后一块石头的重量 II dp
    5779. 装包裹的最小浪费空间 二分
    5778. 使二进制字符串字符交替的最少反转次数 字符串 滑动窗口
    474. 一和零 dp
  • 原文地址:https://www.cnblogs.com/harden/p/6607689.html
Copyright © 2011-2022 走看看