P4449 于神之怒加强版

于神之怒加强版

题意即求:

\[\sum _ {i =1} ^ {n} \sum _ { j = 1 } ^ {m} \gcd (i,j) ^ k \]

其中 \(k\) 是与数据组数一起给定的。

数据满足 \(T\le 2 \times 10 ^ 3\)\(n,m,k\le 5 \times 10 ^ 6\)

直接推导:

\[\begin{aligned} & \sum _ {i =1} ^ {n} \sum _ { j = 1 } ^ {m} \gcd (i,j) ^ k \\ = & \sum _ {d = 1} \sum _ {i =1} ^ {n} \sum _ { j = 1 } ^ {m} \left[ \gcd (i,j) = d \right] d ^ k \\ = & \sum _ {d = 1} d ^ k \sum _ {i =1} ^ {\left\lfloor n / d\right \rfloor} \sum _ { j = 1 } ^ {\left\lfloor m / d\right \rfloor} \left[ \gcd (i,j) = 1 \right] \\ = & \sum _ {d = 1} d ^ k \sum _ {i =1} ^ {\left\lfloor n / d\right \rfloor} \sum _ { j = 1 } ^ {\left\lfloor m / d\right \rfloor} \sum _ {e \mid i , e \mid j} \mu (e) \\ = & \sum _ {d = 1} d ^ k \sum _ {e=1} \mu (e) \left\lfloor \dfrac{n}{de}\right \rfloor \left\lfloor \dfrac{m}{de}\right \rfloor \\ = & \sum _ {T=1} \sum _ {d \mid T} \mu \left(\dfrac{T}{d}\right) d ^ k \left\lfloor \dfrac{n}{T}\right \rfloor \left\lfloor \dfrac{m}{T}\right \rfloor \\ =& \sum _ {T=1} \left(\sum _ {d \mid T} \mu \left(\dfrac{T}{d}\right) d ^ k \right)\left\lfloor \dfrac{n}{T}\right \rfloor \left\lfloor \dfrac{m}{T}\right \rfloor \end{aligned} \]

括号内函数可以 \(O(n \ln n)\) 预处理出前缀和。

后面的是个整除分块。

时间复杂度 \(O(n\ln n + T\sqrt{n})\)

代码:

#include<iostream>
#include<cstdio>
#define ll long long
using namespace std;
namespace Ehnaev{
  inline ll read() {
    ll ret=0,f=1;char ch=getchar();
    while(ch<48||ch>57) {if(ch==45) f=-f;ch=getchar();}
    while(ch>=48&&ch<=57) {ret=(ret<<3)+(ret<<1)+ch-48;ch=getchar();}
    return ret*f;
  }
  inline void write(ll x) {
    static char buf[22];static ll len=-1;
    if(x>=0) {do{buf[++len]=x%10+48;x/=10;}while(x);}
    else {do{buf[++len]=-(x%10)+48;x/=10;}while(x);}
    while(len>=0) putchar(buf[len--]);
  }
}using Ehnaev::read;using Ehnaev::write;
inline void writeln(ll x) {write(x);putchar(10);}

const ll mo=1e9+7,N=5e6;

ll T,k,n,m,cnt;
ll f[N+5],sf[N+5];
ll mu[N+5],prime[N+5];
bool ff[N+5];

inline ll Qpow(ll b,ll p) {
  ll r=1;while(p) {if(p&1) r=r*b%mo;b=b*b%mo;p>>=1;}return r;
}

inline void Init() {
  ff[1]=1;mu[1]=1;
  for(ll i=2;i<=N;i++) {
    if(!ff[i]) {prime[++cnt]=i;mu[i]=mo-1;}
    for(ll j=1;j<=cnt&&prime[j]*i<=N;j++) {
      ff[i*prime[j]]=1;
      if(i%prime[j]==0) {mu[i*prime[j]]=0;break;}
      mu[i*prime[j]]=mu[i]*(mo-1)%mo;
    }
  }
  for(ll i=1;i<=N;i++) {
    ll tmp=Qpow(i,k);
    for(ll j=i,c=1;j<=N;j+=i,c++) {f[j]=(f[j]+mu[c]*tmp%mo)%mo;}
  }
  for(ll i=1;i<=N;i++) {sf[i]=(sf[i-1]+f[i])%mo;}
}

int main() {

  T=read();k=read();Init();

  while(T--) {
    ll ans=0;
    n=read();m=read();
    for(ll i=1,j;i<=n&&i<=m;i=j+1) {
      j=min(n/(n/i),m/(m/i));
      ans=(ans+(((sf[j]-sf[i-1]+mo)%mo)*(n/i)%mo)*(m/i)%mo)%mo;
    }
    writeln(ans);
  }

  return 0;
}
posted @ 2023-02-03 12:10  Aryper  阅读(21)  评论(0编辑  收藏  举报