https://nanti.jisuanke.com/t/31448c++
已知a序列,给你一个n和m求小于n与m互质的数做为a序列的下标的和ui
打表发现ai=i*(i+1)。spa
易得前n项和为 Sn=n*(n+1)(2*n+1)/6+n*(n+1)/2;咱们直接求与m互质的数较难,因此咱们能够换个思路,求与 m不互质的数,那么与m不互质的数,是取m的素因子的乘积(由于根据惟一分解定理,任意个数均可看做的素数积),那么咱们将m分解质因数,经过容斥定理,就能够得道与m不互质的数,总和sum减去这些数对应的a的和就是答案了。code
区间中与i不互质的个数 = (区间中i的每一个质因数的倍数个数)-(区间中i的每两个质因数乘积的倍数)+(区间中i的每3个质因数的成绩的倍数个数)-(区间中i的每4个质因数的乘积)+...blog
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 1e4 + 10; const int mod = 1e9 + 7; ll inv6=166666668; ll inv2=500000004; ll a[maxn]; ll cal(ll n,ll x){ n/=x; return (n*(n+1)%mod*(2*n+1)%mod*inv6%mod*x%mod*x%mod+n*(n+1)%mod*inv2%mod*x%mod)%mod; } int main(){ ll n,m; while(~scanf("%lld%lld",&n,&m)){ ll tot = cal(n,1); int cnt=0; for(ll i=2;i*i<=m;i++){ if(m%i==0){ a[cnt++]=i; while(m%i==0) m/=i; } } if(m!=1) a[cnt++]=m; ll res=0; for(int i=1;i<(1<<cnt);i++){ ll tmp=1; for(int j=0;j<cnt;j++){ if((1<<j)&i){ tmp=tmp*a[j]%mod; } } tmp=cal(n,tmp); if(__builtin_popcount(i)&1) res=(res+tmp)%mod; else res=(res-tmp+mod)%mod; } printf("%lld\n",(tot-res+mod)%mod); } return 0; }