码迷,mamicode.com
首页 > 其他好文 > 详细

1363 最小公倍数之和

时间:2016-09-03 01:03:31      阅读:424      评论:0      收藏:0      [点我收藏+]

标签:

题目来源: SPOJ
基准时间限制:1.5 秒 空间限制:131072 KB 
给出一个n,求1-n这n个数,同n的最小公倍数的和。
例如:n = 6,1,2,3,4,5,6 同6的最小公倍数分别为6,6,6,12,30,6,加在一起 = 66。
由于结果很大,输出Mod 1000000007的结果。
Input
第1行:一个数T,表示后面用作输入测试的数的数量。(1 <= T <= 50000)
第2 - T + 1行:T个数A[i](A[i] <= 10^9)
Output
共T行,输出对应的最小公倍数之和
Input示例
3
5
6
9
Output示例
55
66
279
思路:欧拉函数;
最小公倍数可以表示为n*m/gcd(n,m);那么要求的就可以写为sum(i,N)= N*sum(i/gcd(N,i));我们把式子再化下就是(N/gcd(N,i))*gcd(N,i)*sum(i/gcd(N,i));
那么后面i/gcd(N,i)是与N/gcd(N,i)互质的数,那么当那么sum(i/gcd(N,i)),就是oula(N/gcd(N,i))*(N/gcd(N,i))/2;N/gcd(N,i)为N的约数,所以只要求所有N的约数,那么分解N,dfs求约数。
  1 #include<stdio.h>
  2 #include<algorithm>
  3 #include<iostream>
  4 #include<string.h>
  5 #include<queue>
  6 #include<math.h>
  7 #include<set>
  8 #include<vector>
  9 #include<string.h>
 10 using namespace std;
 11 typedef long long LL;
 12 bool prime[100010];
 13 int ans[100010];
 14 int ak[105];
 15 int cnt[105];
 16 int p;
 17 int fin[100001];
 18 int oula[100010];
 19 const int mod = 1000000007;
 20 void slove(LL n);
 21 void dfs(int n,int m,int c,int r);
 22 int  quick(int n,int m);
 23 int main(void)
 24 {
 25     int T;
 26     LL n;
 27     scanf("%d",&T);
 28     int i,j;
 29     for(i = 2; i < 1000; i++)
 30     {
 31         if(!prime[i])
 32         {
 33             for(j = i; (i*j) <= 100005; j++)
 34             {
 35                 prime[i*j] = true;
 36             }
 37         }
 38     }
 39     int cn = 0;
 40     for(i = 2; i <= 100005 ; i++)
 41     {
 42         if(!prime[i])
 43             ans[cn++] = i;
 44     }
 45     while(T--)
 46     {
 47         scanf("%lld",&n);
 48         slove(n);
 49     }
 50     return 0;
 51 }
 52 void slove(LL n)
 53 {
 54     int f = 0;
 55     int c = 0;
 56     int t = -1;
 57     p = 0;
 58     LL pp = n;
 59     memset(cnt,0,sizeof(cnt));
 60     while(n > 1)
 61     {
 62         while(n%ans[f] == 0)
 63         {
 64             if(c == 0)
 65             {
 66                 c = 1;
 67                 t++;
 68                 ak[t] = ans[f];
 69                 cnt[t]++;
 70             }
 71             else cnt[t]++;
 72             n/=ans[f];
 73         }
 74         c = 0;
 75         f++;
 76         if(ans[f]*ans[f]>n)
 77             break;
 78     }
 79     if(n>1)
 80     {
 81         t++;
 82         ak[t]=n;
 83         cnt[t]++;
 84     }
 85     dfs(0,t+1,1,1);
 86     LL sum = 0;
 87     int i;
 88     for(i = 0; i < p; i++)
 89     {
 90         sum =(sum+((LL)oula[i]*(LL)fin[i]/2)%mod)%mod;
 91     }
 92     printf("%lld\n",(sum+1)*(LL)pp%mod);
 93 }
 94 void dfs(int n,int m,int c,int r)
 95 {
 96     if(n == m)
 97     {
 98         fin[p] = c;
 99         oula[p++] = r;
100         return ;
101     }
102     int s = 1;
103     int i;
104     for(i = 0; i <= cnt[n]; i++)
105     {
106         if(s==1)
107         {
108             dfs(n+1,m,c*s,r);
109         }
110         else
111         {
112             dfs(n+1,m,c*s,r*s/ak[n]*(ak[n]-1));
113         }
114         s *= ak[n];
115     }
116 }

 


1363 最小公倍数之和

标签:

原文地址:http://www.cnblogs.com/zzuli2sjy/p/5835982.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!