题目:最小公倍数之和
sol:
1.qls的式子(见51nod讨论区):
2.弱鸡的式子
我们设
喜闻乐见的是,这玩意是有结论的,即
如何证明呢?
1) 考虑若 ,则有 对于 成立
假设 且
设 且
则
与假设 矛盾,上式得证
2)由1)我们可以观察到1~ 中与 互质的数成对出现,且每对之和为n。当n为1时只有1单独出现,则 得证。
继续推式子
扫描二维码关注公众号,回复:
3416909 查看本文章
3.dfs求解
朴素的因数分解是
,不能在时限内完成。
由反素数可知一个数的因子并不多,考虑质因数分解并搜索因数求解。
预处理素数之后质因数分解复杂度大概是
然后这个题就可以
了
code:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+10;
const int mod = 1e9+7;
const int inv2 = (mod >> 1) + 1;
typedef long long ll;
int primes[maxn];
bool check[maxn];
int oula[maxn];
int tot;
ll ans;
void init(){
tot = 0;
oula[1] = 1;
for(int i = 2;i<maxn;i++){
if(!check[i]){
primes[++tot] = i;
oula[i] = i - 1;
}
for(int j = 1;j<=tot;j++){
if(i*primes[j]>=maxn) break;
check[i*primes[j]] = true;
if(i % primes[j] == 0){
oula[i*primes[j]] = oula[i] * primes[j];
break;
}
else{
oula[i*primes[j]] = oula[i] * (primes[j] - 1);
}
}
}
}
int e[maxn],p[maxn],cnt;
ll sta[maxn];
int top;
ll Mul(ll a,ll b){
ll ret = a*b;
if(ret >= mod) ret%=mod;
return ret;
}
void Add(ll& x,ll y){
x+=y;
if(x>=mod) x-=mod;
}
void dfs(ll pos,ll val,ll Euler){
if(pos == cnt + 1){
ll ret = Mul(val,Euler);
Add(ans,ret);
// cout<<val<<' '<<Euler<<' '<<ret<<' '<<ans<<endl;
return ;
}
ll ret = val;
dfs(pos+1,val,Euler);
ret *= p[pos];
ll eu = Euler * (p[pos] - 1);
if(e[pos]>0) dfs(pos+1,ret,eu);
for(int i = 2;i<=e[pos];i++){
ret *= p[pos];
eu *= p[pos];
dfs(pos+1,ret,eu);
}
}
int main(){
init();
int T;
scanf("%d",&T);
e[0] = 0;
p[0] = 1;
while(T--){
ll n;
scanf("%d",&n);
cnt = 0;
int tmp = n;
for(int i = 1;i<=tot;i++){
if((ll)primes[i] * primes[i] > tmp) break;
if(tmp % primes[i] == 0){
p[++cnt] = primes[i];
e[cnt] = 0;
while(tmp%primes[i]==0){
e[cnt]++;
tmp/=primes[i];
}
}
}
if(tmp!=1) {
e[++cnt] = 1;
p[cnt] = tmp;
}
ans = 1;
dfs(0,1,1);
ans = ans * n % mod * inv2 % mod;
printf("%lld\n",ans);
}
return 0;
}