1. 程式人生 > >BZOJ#4407. 於神之怒加強版

BZOJ#4407. 於神之怒加強版

預處理 code line scrip scanf 約束 eight spa 只需要


4407: 於神之怒加強版

Time Limit: 80 Sec Memory Limit: 512 MB
Submit: 1302 Solved: 582

Description

給下N,M,K.求 技術分享圖片

Input

輸入有多組數據,輸入數據的第一行兩個正整數T,K,代表有T組數據,K的意義如上所示,下面第二行到第T+1行,每行為兩個正整數N,M,其意義如上式所示。

Output

如題

Sample Input

1 2
3 3

Sample Output

20

HINT

1<=N,M,K<=5000000,1<=T<=2000


problem:
求:

技術分享圖片

solution: 預處理出h數組,實現技術分享圖片的復雜度 推導:

                      技術分享圖片

枚舉gcd:

             技術分享圖片

套路化解:

            技術分享圖片

根據公式二:

            技術分享圖片

套路枚舉dx:

             技術分享圖片

考慮預處理出:        

                技術分享圖片

化解一下:         
              技術分享圖片 因為積性函數的約束和也是積性函數,所以h是積性函數:

               技術分享圖片

線性篩時預處理出h數組: 註意: 如果i%prime[j]==0:則μ(i*prime[j])及以後都為0,不再為h做出貢獻,只有D為變。

                    技術分享圖片

                    技術分享圖片

我們只需要合並時把h乘上一個技術分享圖片即可 否則,根據積性函數性質:h(i*prime[j])=h(i)*h(prime[j]),更新即可。
void getmu()
{
    h[1]=1;
    for(int
i=2;i<=N;i++) { if(!vis[i]) { prime[++cnt]=i; g[i]=qpow(k,i); h[i]=(g[i]-1+mod)%mod; } for(int j=1;j<=cnt;j++) { if(i*prime[j]>N) break; vis[i*prime[j]]=1; if(i%prime[j]==0) {h[i*prime[j]]=(h[i]*g[prime[j]])%mod;break;} h[i*prime[j]]=(h[i]*h[prime[j]])%mod; } } for(int i=1;i<=N;i++) h[i]=(h[i]+h[i-1])%mod; }

附上代碼:技術分享圖片

#include<bits/stdc++.h>
using namespace std;
const int N=5e6+12;
const int mod=1e9+7;
int prime[N],cnt,vis[N];
long long h[N],g[N];//註意long long 
long long k;
int n,m;
int qpow(int a,long long b)
{
    long long ans=1;
    while(a)
    {
        if(a&1) ans=ans*b%mod;
        b=b*b%mod;
        a>>=1;
    }
    ans%=mod;
    return ans;
}

void getmu()
{
    h[1]=1;
    for(int i=2;i<=N;i++) 
    {
        if(!vis[i]) 
        {
            prime[++cnt]=i;
            g[i]=qpow(k,i);
            h[i]=(g[i]-1+mod)%mod;
        }
        for(int j=1;j<=cnt;j++) 
        {
            if(i*prime[j]>N) break;
            vis[i*prime[j]]=1;
            if(i%prime[j]==0) {h[i*prime[j]]=(h[i]*g[prime[j]])%mod;break;}
            h[i*prime[j]]=(h[i]*h[prime[j]])%mod;
        }
    }
    for(int i=1;i<=N;i++) h[i]=(h[i]+h[i-1])%mod;
}
int main()
{
    freopen("a.in","r",stdin);
    int T;scanf("%d%d",&T,&k);
    getmu();
    while(T--) 
    {
        scanf("%d%d",&n,&m);
        if(n>m) swap(n,m);
        int pos;
        long long ans=0;
        for(int i=1;i<=n;i=pos+1) 
        {
            pos=min(n/(n/i),m/(m/i));
            long long t=(long long)(n/i)*(m/i)%mod;
            ans=(ans+(long long)t*(h[pos]-h[i-1]+mod)%mod)%mod;
        }
        ans=(ans%mod+mod)%mod;
        printf("%lld\n",ans);
    }
    return 0;
}


BZOJ#4407. 於神之怒加強版