大致題意:自己看吧……
直接上莫比烏斯反演。
令,顯然g是一個積性函數,我們考慮用杜教篩求它的前綴和。
如此杜教篩即可求出S(n)。
考慮求:
如此,變成一個等比數列的和,注意需要特殊處理q=1的情況。由於,因此直接對l數論分塊即可。另外,K很大,不過我們可以用歐拉降冪來處理。總的時間複雜度爲具體見代碼:
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f3f3f3f3fll
#define eps 1e-6
#define LL long long
#define pb push_back
#define fi first
#define se second
#define cl clear
#define si size
#define lb lower_bound
#define ub upper_bound
#define bug(x) cerr<<#x<<" : "<<x<<endl
#define mem(x) memset(x,0,sizeof x)
#define sc(x) scanf("%d",&x)
#define scc(x,y) scanf("%d%d",&x,&y)
#define sccc(x,y,z) scanf("%d%d%d",&x,&y,&z)
using namespace std;
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
const int inv6 = 166666668;
unordered_map<int,int> mp;
int s[N],p[N],sz,n;
char str[N];
bool isp[N];
LL k1,k2;
inline LL qpow(LL x,LL n)
{
LL res=1;
while(n)
{
if (n&1) res=res*x%mod;
x=x*x%mod; n>>=1;
}
return res;
}
inline void init()
{
s[1]=1;
for(int i=2;i<N;i++)
{
if(!isp[i])p[++sz]=i,s[i]=(LL)i*i%mod-1;
for(int j=1;j<=sz&&i*p[j]<N;j++)
{
isp[i*p[j]]=1;
if(i%p[j]==0)
{
s[p[j]*i]=(LL)s[i]*p[j]%mod*p[j]%mod; break;
} else s[p[j]*i]=(LL)s[p[j]]*s[i]%mod;
}
}
for(int i=2;i<N;i++)
s[i]=(s[i]+s[i-1])%mod;
}
inline LL S(int n)
{
if (n<N) return s[n];
if (mp[n]) return mp[n];
LL res=(LL)n*(n+1)%mod*(2*n+1)%mod*inv6%mod;
for(int l=2,r;l<=n;l=r+1)
{
int tmp=n/l;
r=n/tmp; res=(res-(r-l+1)*S(tmp)%mod+mod)%mod;
}
return mp[n]=res;
}
inline LL Sum(int q)
{
if (q==1) return k2-1;
return (LL)q*q%mod*(qpow(q,k1-1)-1)%mod*qpow(q-1,mod-2)%mod;
}
int main()
{
init();
int T; sc(T);
while(T--)
{
LL ans=0;
sc(n); scanf("%s",str);
if (strlen(str)<10) k1=k2=atoi(str);
else
{
k1=k2=0;
for(int i=0;str[i];i++)
{
k1=(k1*10%(mod-1)+str[i]-48)%(mod-1);
k2=(k2*10%mod+str[i]-48)%mod;
}
k1+=mod-1;
}
for(int l=1,r,last=0;l<=n;l=r+1)
{
int q=n/l; r=n/q; LL tmp=S(r);
ans=(ans+(tmp-last+mod)*Sum(q)%mod)%mod;
last=tmp;
}
printf("%lld\n",ans);
}
return 0;
}