题目传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4407
题目分析:又是一道老年人数论题。
不妨令 n≤m n ≤ m 。经过一番推导倒,可以得到这个:
令 G(i)=ik G ( i ) = i k ,它是个完全积性函数,可以通过预处理所有质数的 G G 然后线性筛得到。求质数的 G G 值可以用快速幂。由于质数个数是 nln(n) n ln ( n ) 级别的,所以这部分时间为 O(nlog(k)ln(n)) O ( n log ( k ) ln ( n ) ) 。又因为 n,k n , k 大小相近,可以认为接近 O(n) O ( n ) 。
第二个 ∑ ∑ 后面的式子记为 F(D) F ( D ) ,它是 G G 卷 μ μ ,所以也是积性函数。令 p p 为质数,则可以预处理全部 F(pq) F ( p q ) ,然后用线性筛得到所有 F F 值。根据定义显然有 F(pq)=G(pq)−G(pq−1) F ( p q ) = G ( p q ) − G ( p q − 1 ) 。然后对于每个询问下底函数分块,总时间为 O(n+Tn−−√) O ( n + T n ) 。
一开始 G G 数组乘起来的时候忘了取模,WA了一次。
CODE:
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int maxn=5000010;
const long long M=1000000007;
typedef long long LL;
int p[maxn];
LL G[maxn];
LL F[maxn];
bool vis[maxn];
int prime[maxn];
int cur=0;
int t,n,m,k;
LL Fast_power(LL x,LL y)
{
if (!y) return 1LL;
LL temp=Fast_power(x,y>>1);
temp=temp*temp%M;
if (y&1) temp=temp*x%M;
return temp;
}
void Linear_shaker()
{
G[1]=1;
for (int i=2; iif (!vis[i]) G[i]=Fast_power(i,k),p[i]=i,prime[++cur]=i;
for (int j=1; j<=cur && i*prime[j]int K=i*prime[j];
vis[K]=true;
G[K]=G[i]*G[ prime[j] ]%M;
if (i%prime[j]) p[K]=prime[j];
else
{
p[K]=p[i]*prime[j];
break;
}
}
}
F[1]=1LL;
for (int i=1; i<=cur; i++)
{
LL x=prime[i],last=1;
while (x<(long long)maxn)
{
F[x]=(G[x]-G[last]+M)%M;
last=x;
x*=(long long)prime[i];
}
}
for (int i=2; iif (p[i]for (int i=1; i1]+F[i])%M;
}
int main()
{
freopen("4407.in","r",stdin);
freopen("4407.out","w",stdout);
scanf("%d%d",&t,&k);
Linear_shaker();
while (t--)
{
scanf("%d%d",&n,&m);
if (n>m) swap(n,m);
LL ans=0;
int last;
for (int i=1; i<=n; i=last+1)
{
last=min( n/(n/i) , m/(m/i) );
ans=(ans+ (long long)(n/i)*(m/i)%M*( F[last]-F[i-1]+M )%M )%M;
}
printf("%I64d\n",ans);
}
return 0;
}