zoukankan      html  css  js  c++  java
  • Bzoj2154 Crash的数字表格

    Time Limit: 20 Sec  Memory Limit: 259 MB
    Submit: 3325  Solved: 1247

    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。

    HINT

     

    Source

    数学问题 莫比乌斯反演

     

    题目要求的是这个:    很明显也就是  

     

    如果我们要求  ,可以这么搞:

      i和j都带进等差数列公式,设上式为函数sum[N,M],则 $sum[N,M]=(N(N+1)/2)*(M(M+1)/2)$

    如果要求gcd(i,j)的和,也有方便的方法:http://www.cnblogs.com/SilverNebula/p/6582843.html

    当然不可以分别算上面和下面,然后两式相除,但是↑这里的分块求值方法给了我们一定启发:对于gcd(i,j)相等的一段i和j,上面除以下面满足除法分配律,是可行的。

    枚举因数d=gcd(i,j),则可以化成  ,这个是可以求的

    枚举累加过程会有重复算的部分,这时候就需要莫比乌斯函数来解决问题了

     

    为了表示方便,令a=N/d,b=M/d

    我们可以搞出

    这个东西累加一下就是我们要的结果:

    加上LL以后就突然各种挂,调了好久

     1 /*by SilverN*/
     2 #include<algorithm>
     3 #include<iostream>
     4 #include<cstring>
     5 #include<cstdio>
     6 #include<cmath>
     7 #include<vector>
     8 #define LL long long
     9 using namespace std;
    10 const LL inv2=10050505;
    11 const LL mod=20101009;
    12 const int mxn=10000010;
    13 int pri[mxn],cnt=0;
    14 int mu[mxn];
    15 LL smm[mxn];
    16 bool vis[mxn];
    17 void init(){
    18     mu[1]=1;
    19     for(int i=2;i<mxn;i++){
    20         if(!vis[i]){
    21             pri[++cnt]=i;
    22             mu[i]=-1;
    23         }
    24         for(int j=1;j<=cnt && (LL)pri[j]*i<mxn;j++){
    25             vis[i*pri[j]]=1;
    26             if(i%pri[j]==0){mu[i*pri[j]]=0;break;}
    27             mu[i*pri[j]]=-mu[i];
    28         }
    29     }
    30     for(int i=1;i<mxn;i++)smm[i]=(smm[i-1]+(LL)i*mu[i]*i)%mod;
    31     return;
    32 }
    33 int SUM(int x,int y){
    34     return ((LL)x*(x+1)%mod*inv2%mod)*((LL)y*(y+1)%mod*inv2%mod)%mod;
    35 }
    36 inline int s1(int x){return (x*(x+1)%mod*inv2%mod);} 
    37 LL calc(int a,int b){
    38     LL res=0;int pos;
    39     if(a>b)swap(a,b);
    40     for(int i=1;i<=a;i=pos+1){
    41         int x=a/i,y=b/i;
    42         pos=min(a/x,b/y);
    43         res+=(smm[pos]-smm[i-1])*SUM(x,y);
    44         res%=mod;
    45     }
    46     return res;
    47 }
    48 int solve(int a,int b){
    49     LL res=0;int pos;
    50     if(a>b)swap(a,b);
    51     for(int i=1;i<=a;i=pos+1){
    52         int x=a/i,y=b/i;
    53         pos=min(a/x,b/y);
    54         (res+=(s1(pos)-s1(i-1))*calc(x,y))%=mod;
    55     }
    56     return res;
    57 }
    58 LL n,m;
    59 int main(){
    60     int i,j;
    61     init();
    62     cin>>n>>m;
    63     printf("%d
    ",solve(n,m));
    64     return 0;
    65 }
  • 相关阅读:
    毕业设计-1.11
    毕业设计-1.10
    毕业设计-1.09
    毕业设计-1.08
    毕业设计-1.07
    [工具]Maven的安装和配置【MyEclipse】
    毕业设计-1.06
    tomcat部署项目时省略项目名
    Jenkins实现iOS项目自动化打包(含踩坑记录)
    钉钉小程序封装网络请求
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/6593631.html
Copyright © 2011-2022 走看看