1. 程式人生 > >hdu6069 多校Counting Divisors

hdu6069 多校Counting Divisors

urn def ever http 16px += () 判斷 ons

  技術分享

   思路:對於n^k其實就是每個因子的個數乘了一個K。然後現在就變成了求每個數的每個質因子有多少個,但是比賽的時候只想到sqrt(n)的分解方法,總復雜度爆炸,就一直沒過去,然後賽後看官方題解感覺好妙啊!通過類似素數篩法的方式,把L - R的質因子給分解,就可以在O(nlogn)的時間之內把所以的數給篩出來。

/*  gyt
       Live up to every day            */

#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include
<vector> #include<stack> #include<cstring> #include<queue> #include<set> #include<string> #include<map> #include <time.h> #define PI acos(-1) using namespace std; typedef long long ll; typedef double db; const int maxn = 1e6+10; const ll maxm = 1e7; const
ll mod = 998244353; const int INF = 0x3f3f3f; const ll inf = 1e15 + 5; const db eps = 1e-9; int is[maxn], pri[maxn]; ll f[maxn], num[maxn]; int cnt; ll r, l, k; void prim() { cnt=0; memset(is, 0, sizeof(is)); memset(pri, 0, sizeof(pri)); for (int i=2; i<maxn; i++) { if (!is[i]) { pri[
++cnt]=i; for (int j=i+i; j<maxn; j+=i) { is[j]=1; } } } } void solve() { scanf("%lld%lld%lld", &l, &r, &k); for (ll i=l; i<=r; i++) { f[i-l+1]=1, num[i-l+1]=i; } for (int i=1; i<=cnt; i++) { ll be=l+pri[i]-l%pri[i]; if (l%pri[i]==0) be=l; for (ll j=be; j<=r; j+=pri[i]) { ll sum=0; while (num[j-l+1]%pri[i]==0) { sum++; num[j-l+1]/=pri[i]; } f[j-l+1]=f[j-l+1]*(k*sum%mod+1)%mod; } } ll ans=0; for (ll i=l; i<=r; i++) { if (num[i-l+1]!=1) f[i-l+1]=f[i-l+1]*(k+1)%mod; ans=(ans+f[i-l+1])%mod; } cout<<ans<<endl; } int main() { int t = 1; //freopen("in.txt", "r", stdin); scanf("%d", &t); prim(); while(t--) solve(); return 0; }

  解釋:

for (ll i=l; i<=r; i++) {
        f[i-l+1]=1, num[i-l+1]=i;
}

  如果不進行這一步,那麽數是1~1^12存不下,但是我們已知r-l<=1e6,這樣就可以存下了。

  f[i]表示當前的因數個數,num[i],從l到r(下標1-(r-l+1))的數。

for (ll i=l; i<=r; i++) {
        if (num[i-l+1]!=1)  f[i-l+1]=f[i-l+1]*(k+1)%mod;
        ans=(ans+f[i-l+1])%mod;
}

  判斷當前這個數還有沒有素數因子。

hdu6069 多校Counting Divisors