看到好多大神留下的題解能看得懂,但是對於那個線性篩我表示我是蒟蒻我不會QAQ~
於是我決定來水一發(順便留下這道權限題,什麼時候有權限了再去交一(交易)發)
目前找了個過了的代碼對拍發現並無錯誤&& 測試時間大致和那份程序差不多(應該能過吧~~)
題意:
n m
求 ∑ ∑ gcd(i,j)^k mod 1e9+7
i=1 j=1
min(n,m) n m
先枚舉gcd(i,j).轉化爲求 ∑ d^k ∑ ∑ [gcd(i,j)==d]
d=1 i=1 j=1
思路:
n m
ans=∑ ∑ gcd(i,j)^k
i=1 j=1
n m
ans=∑ d^k(∑ ∑ [gcd(i,j)==d] )
d=1 i=1 j=1
min(n,m) min(n/d,m/d)
ans=∑ d^k ∑ u(t) *[n/dt]*[m/dt]
d=1 t=1
min(n,m) min(n/d,m/d)
ans=∑ d^k ∑ u(T/d) *[n/T]*[m/T]
d=1 T/d=1
min(n,m)
ans=∑ [n/T]*[m/T] ∑ u(T/d) *d^k
T=1 d|T
如果能線性篩出G(T)=∑ u(T/d) *d^k
d|T
因爲G(T)中d^k和u(T/d)都是積性函數,且又是相乘,所以G(T)是積性函數
把G(T)展開(用所有的因子)
t t t
G(T)=π G(pi^xi) = π ∑ u(pi^xi/d) *d^k =π u(pi)*pi^(xi-1)^k + u(1)*pi^xi^k
i=1 i=1 d|pi^xi i=1
t t
=π -pi^[k*(xi-1)]+pi^[xi*k] =π pi^[k*(xi-1)](pi^k-1)
i=1 i=1
然後線性一波篩:
對於質數,我們求pi^k -1 .
不是質數的:(在枚舉prime的時候)
如果是該質數的倍數,i*prime[j]就乘上prime[j]^k (一共有xi-1個這樣的),因爲pi^k-1已經計算過了。
如果不是倍數,就一定互質(prime[j]是質數),因爲有連乘號,就乘起來。
附代碼(跪求路過的有權限的幫我交一發,謝謝,while(1)orz;):
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cmath>
#include<iostream>
#include<cstring>
#include<cstdlib>
#define ll long long
using namespace std;
const int maxn=5000000+5;
const ll M=1e9+7;
/*
n,m,k;
n m
ans=∑ ∑ gcd(i,j)^k
i=1 j=1
n m
ans=∑ d^k(∑ ∑ [gcd(i,j)==d] )
d=1 i=1 j=1
min(n,m) min(n/d,m/d)
ans=∑ d^k ∑ u(t) *[n/dt]*[m/dt]
d=1 t=1
min(n,m) min(n/d,m/d)
ans=∑ d^k ∑ u(T/d) *[n/T]*[m/T]
d=1 T/d=1
min(n,m)
ans=∑ [n/T]*[m/T] ∑ u(T/d) *d^k
T=1 d|T
如果能線性篩出G(T)=∑ u(T/d) *d^k
d|T
因爲G(T)中d^k和u(T/d)都是積性函數,且又是相乘,所以G(T)是積性函數
把G(T)展開(用所有的因子)
t t t
G(T)=π G(pi^xi) = π ∑ u(pi^xi/d) *d^k =π u(pi)*pi^(xi-1)^k + u(1)*pi^xi^k
i=1 i=1 d|pi^xi i=1
t t
=π -pi^[k*(xi-1)]+pi^[xi*k] =π pi^[k*(xi-1)](pi^k-1)
i=1 i=1
*/
ll n,m,k;
bool flag[maxn];
int prime[maxn];
int tot;
ll g[maxn];
ll sum[maxn];//g[i]的前綴和
ll qk(ll x,ll y)
{
ll res=1;
x%=M;
while(y)
{
if(y&1)res=res*x%M;
y>>=1;
x=x*x%M;
}
return res;
}
void init()
{
g[1]=1;
tot=0;
for(int i=2;i<=maxn;i++)
{
if(!flag[i])
{
prime[++tot]=i;
g[i]=qk((ll)i,k)-1;
}
for(int j=1;j<=tot&&i*prime[j]<=maxn;j++)
{
flag[i*prime[j]]=1;
if(i%prime[j]==0)
{
g[i*prime[j]]=g[i]*qk((ll)prime[j],k)%M;
break;
}
else g[i*prime[j]]=g[i]*g[prime[j]]%M;
}
}
for(int i=1;i<=maxn;i++)sum[i]=sum[i-1]+g[i];
}
int main()
{
int T;
scanf("%d%lld",&T,&k);
init();
while(T--)
{
scanf("%lld%lld",&n,&m);
// min(n,m)
//ans=∑ [n/T][m/T]G(T)
// T=1
ll ans=0;
ll h=min(n,m);
int pos;
for(int i=1;i<=h;i=pos+1)
{
pos=min(n/(n/i),m/(m/i));
ans+=(sum[pos]-sum[i-1])%M*(n/i)%M*(m/i);
ans%=M;
}
printf("%lld\n",ans);
}
return 0;
}