例如:n = 6,1,2,3,4,5,6 同6的最小公倍数分别为6,6,6,12,30,6,加在一起 = 66。
第1行:一个数T,表示后面用作输入测试的数的数量。(1 <= T <= 50000) 第2 - T + 1行:T个数A[i](A[i] <= 10^9)
共T行,输出对应的最小公倍数之和
3 5 6 9
55 66 279
思路:这题数据很大,还需要一些剪枝,不然过不去;
首先最小公倍数的和,不考虑时间复杂度,
求法:
首先你需要知道有个这样的定理:如果 gcd(n,i)=1则 gcd(n,n-i)=1 (1<=i<=n)
欧拉函数是积性函数——若m,n互质,φ(mn)=φ(m)φ(n)。
若n是质数p的k次幂,φ(n)=p^k-p^(k-1)=(p-1)p^(k-1),因为除了p的倍数外,其他数都跟n互质。
#include<bits/stdc++.h> using namespace std; #define ll long long #define mod 1000000007 #define inf 999999999 #define esp 0.00000000001 ll scan() { ll res = 0 , ch ; while( !( ( ch = getchar() ) >= '0' && ch <= '9' ) ) { if( ch == EOF ) return 1 << 30 ; } res = ch - '0' ; while( ( ch = getchar() ) >= '0' && ch <= '9' ) res = res * 10 + ( ch - '0' ) ; return res ; } const int MAXN=32000; int fa[100]; int si[100],p; ll ans; int prime[MAXN],cnt; bool vis[MAXN]; inline int Prime(int n) { cnt=0; memset(vis,0,sizeof(vis)); for(int i=2;i<n;i++) { if(!vis[i]) prime[cnt++]=i; for(int j=0;j<cnt&&i*prime[j]<n;j++) { vis[i*prime[j]]=1; if(i%prime[j]==0) break; } } return cnt; } inline void dfs(ll fac,ll pos,ll x,ll oula) { if(pos==p) { ans+=oula*fac/2; ans%=mod; return; } ll base=1; ll hh=1; for(int i=0;i<=si[pos];i++) { dfs(fac*base,pos+1,x,oula*hh); base*=fa[pos]; hh*=fa[pos]-(i==0?1:0); } } int main() { ll x,y,z,i,t; Prime(MAXN); int T; scanf("%d",&T); while(T--) { memset(si,0,sizeof(si)); scanf("%lld",&x); ans=0; p=0; z=x; for(i=0;i<cnt&&prime[i]*prime[i]<=z;i++) { if(z%prime[i]==0) { fa[p]=prime[i]; while(z%prime[i]==0) { z/=prime[i]; si[p]++; } p++; } } if(z>1) { fa[p]=z; si[p++]++; } dfs(1,0,x,1); printf("%lld\n",(x*(ans+1))%mod); } return 0; }