bzoj4407於神之怒

看到好多大神留下的題解能看得懂,但是對於那個線性篩我表示我是蒟蒻我不會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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章