https://nanti.jisuanke.com/t/31448
解析 易得an=n*n+n O(1)得到前n项和 再删除与m不互素的数 我们用欧拉函数求出m的质因数 枚举其集合的子集 进行容斥
n*n+n+2n*2n+2n+3n*3n+3n=(1+4+9)*n*n+(1+2+3)*n 所以也可以O(1)得到。
AC代码
#include <bits/stdc++.h> #define pb push_back #define mp make_pair #define fi first #define se second #define all(a) (a).begin(), (a).end() #define fillchar(a, x) memset(a, x, sizeof(a)) #define huan printf(" "); #define debug(a,b) cout<<a<<" "<<b<<" "; using namespace std; const int maxn=1e5+100,inf=0x3f3f3f3f; typedef long long ll; typedef pair<int,int> pii; const ll mod=1e9+7; int yin[maxn],cnt; void euler(ll n) //返回euler(n) { ll res=n,a=n; cnt=0; for(ll i=2; i*i<=a; i++) { if(a%i==0) { yin[cnt++]=i; res=res/i*(i-1);//先进行除法是为了防止中间数据的溢出 爆int while(a%i==0) a/=i; } } if(a>1) res=res/a*(a-1),yin[cnt++]=a; } ll powmod(ll n,ll m) { ll ans=1; while(m>0) { if(m&1) ans=ans*n%mod; m = m>>1; n = n*n%mod; } return ans; } ll inv2=powmod(2,mod-2); ll inv6=powmod(6,mod-2); ll getsum1(ll n) { return n*(n+1)%mod*(2*n%mod+1)%mod*inv6%mod; } ll getsum2(ll n) { return n*(n+1)%mod*inv2%mod; } int main() { ll n,m; while(scanf("%lld%lld",&n,&m)!=EOF) { euler(m); ll ans=(getsum1(n)+getsum2(n))%mod; for(int i=0; i<(1<<cnt); i++) { ll temp=1,jishu=0; for(int j=0; j<cnt; j++) { if(i&(1<<j)) temp*=yin[j],jishu++; } if(temp==1)continue; ll bei=n/temp; ans=(ans+powmod(-1,jishu)*temp*temp%mod*getsum1(bei)%mod+mod)%mod; ans=(ans+powmod(-1,jishu)*temp*getsum2(bei)%mod+mod)%mod; } printf("%lld ",ans); } }