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; }