A1231. Crash的数字表格(贾志鹏)

A1231. Crash的数字表格(贾志鹏)
时间限制:2.0s   内存限制:512.0MB  
总提交次数:410   AC次数:154   平均分:63.93
 
将本题分享到:
      
   
试题来源
  2011中国国家集训队命题答辩
问题描述
  今天的数学课上,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的表格如下:

  看着这个表格,Crash想到了很多可以思考的问题。不过他最想解决的问题却是一个十分简单的问题:这个表格中所有数的和是多少。当N和M很大时,Crash就束手无策了,因此他找到了聪明的你用程序帮他解决这个问题。由于最终结果可能会很大,Crash只想知道表格里所有数的和mod20101009的值。
输入格式
  输入的第一行包含两个正整数,分别表示N和M。
输出格式
  输出一个正整数,表示表格中所有数的和mod20101009的值。
样例输入
4 5
样例输出
122
数据规模和约定
  30%的数据满足N, M≤ 103。
  70%的数据满足N, M≤ 105。
  100%的数据满足N, M≤ 107。

 

参考:http://blog.csdn.net/regina8023/article/details/44243911

表示看不懂代码

#include<cstdio>
#include<iostream>
using namespace std;
typedef long long ll;
const int N=1e7+5;
const int mod=20101009;
int n,m,tot,mu[N],prime[N/10];bool check[N];
ll sum[N];
void mobius(){
    mu[1]=1;
    for(int i=2;i<=n;i++){
        if(!check[i]) prime[++tot]=i,mu[i]=-1;
        for(int j=1;j<=tot&&i*prime[j]<=n;j++){
            check[i*prime[j]]=1;
            if(!(i%prime[j])){mu[i*prime[j]]=0;break;}
            else mu[i*prime[j]]=-mu[i]; 
        }
    }
    for(int i=1;i<=n;i++) sum[i]=sum[i-1]+(1LL*mu[i]*i%mod*i%mod); 
}
ll SUM(ll x,ll y){
    x=(x*(x+1)>>1)%mod;
    y=(y*(y+1)>>1)%mod;
    return (x*y%mod);
}
ll GET(ll x,ll y){
    ll res=0;
    int pos=0;
    for(int i=1;i<=x;i=pos+1){
        pos=min(x/(x/i),y/(y/i));
        res=(res+(sum[pos]-sum[i-1]+mod)%mod*SUM(x/i,y/i)%mod)%mod; 
    }
    return res;
}
int main(){
    scanf("%d%d",&n,&m);
    if(n>m) swap(n,m);
    mobius();
    ll ans=0;
    int pos=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)>>1)%mod*GET(n/i,m/i)%mod)%mod;
    }
    printf("%lld",ans);
    return 0;
}

 

posted @ 2017-03-20 20:58  神犇(shenben)  阅读(371)  评论(0编辑  收藏  举报