6069 (區間素數篩 + 一個數的所有素因子的個數 + 約數定理 + 數學)
阿新 • • 發佈:2019-02-11
In mathematics, the function d(n)d(n) denotes the number of divisors of positive integer nn.
For example, d(12)=6d(12)=6 because 1,2,3,4,6,121,2,3,4,6,12 are all 1212's divisors.
In this problem, given l,rl,r and kk, your task is to calculate the following thing :
(∑i=lrd(ik))mod998244353(∑i=lrd(ik))mod998244353
InputThe first line of the input contains an integer T (1≤T≤15)T(1≤T≤15), denoting the number of test cases.
In each test case, there are 33 integers l,r,k(1≤l≤r≤1012,r−l≤106,1≤k≤107)l,r,k(1≤l≤r≤1012,r−l≤106,1≤k≤107).OutputFor each test case, print a single line containing an integer, denoting the answer.Sample Input
For example, d(12)=6d(12)=6 because 1,2,3,4,6,121,2,3,4,6,12 are all 1212's divisors.
In this problem, given l,rl,r and kk, your task is to calculate the following thing :
(∑i=lrd(ik))mod998244353(∑i=lrd(ik))mod998244353
InputThe first line of the input contains an integer T
In each test case, there are 33 integers l,r,k(1≤l≤r≤1012,r−l≤106,1≤k≤107)l,r,k(1≤l≤r≤1012,r−l≤106,1≤k≤107).OutputFor each test case, print a single line containing an integer, denoting the answer.Sample Input
3 1 5 1 1 10 2 1 100 3Sample Output
10 48 2302
題意:輸入 l r k 求 l<= t<=r, 求 對多有滿足條件的t 的 d(t^k)=t^k的所有 不同因子的個數 的總和
思路:想求d(t^k),先求 d(t),根據約數定理 求不同因子的個數,先把 t 表示為不同素因子的積的形式;
n=p1^c1×p2^c2×p3^c3*…*pm^cm
d(n) = (C1 + 1)*(C2 + 1)*...... (Cm+1) ;表示不同因子的個數;
c1+1 為從中可以選出 1個p1,2個p1...... c1個p1,加 1就是 一個p1也不選,光p1這個素數就 c1+1 種情況,然後和其他選出的素因子結合;有一種情況就是 所有的素因子都不選,那麼這種情況 就是 n個素因子為1 的這種情況;
理解了d(n),那麼d(n^k)就好理解了
寫程式碼應注意;
1,用三目運算子時,一定要加括號,就這道題而言,不加括號就是超時;
2,程式碼中用到了 區間素數篩, 還有最重要的時,a[] 和 sum[] 陣列,sum[i] 存 sum[l+i] 的素因子個數;
a[i] = l + i; 找到 l+i的素因子時,一直除到不能整除 這個素因子位置;
3,當一個數 n,把1~根號n 中的素數 能除的都除盡了,但最終 n 不為1,那麼這麼剩餘的n一定是個大素數;
我說這個大素數有兩種情況 (1) n 本身為 素數 (2) n 把1~ 根號n中的素數除完之後,剩餘的數為素數;
如 n = 14,14 把 1~根號14 中的素數都除盡後,剩下 7,7為素數;
程式碼:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define ll long long
#define Max 1000000+10
#define mod 998244353
bool is_prime[Max]; // 0~Max 之間的素數
ll prime[Max]; // 存 0~Max 之間的素數;
ll sum[Max]; // sum[i]表示 l+i的因子個數;
ll a[Max]; // a[i] = l+i; 為了素數分解;
ll l,r,k;
ll num;
void Prime()
{
num = 0;
ll i,j;
memset(is_prime,true,sizeof(is_prime));
is_prime[0] = false;
is_prime[1] = false;
for(i = 2;i<Max;i++)
{
if(is_prime[i])
{
prime[num++] = i; // 找出1 ~ 1000000中的素數;
for(j = 2;i*j<Max;j++)
is_prime[i*j] = false;
}
}
}
int main()
{
Prime();
ll i,j,t;
scanf("%lld",&t);
while(t--)
{
scanf("%lld%lld%lld",&l,&r,&k);
for(i = 0;i<=r-l;i++)
{
sum[i] = 1; // 要進行乘法,所以要賦值為1;
a[i] = l+i; // 為了把 a[i] == l+i 進行分解;
}
for(i = 0;i<num;i++)
{
ll temp = (l/prime[i]+((l%prime[i])?1:0))*prime[i];
// 三目運算子一定要加括號;,不加括號超時;
//找到[l,r]中第一個能被這個素數整除的數;
for(j = temp; j<=r; j += prime[i]) // 先找到能整除素數prime[i]的數;
{
ll res = 0;
while(a[j-l]%prime[i]==0) // 把這個數進行素數分解;
{
a[j-l] /= prime[i];
res++;
}
sum[j-l] = (sum[j-l]*((res*k+1)%mod))%mod;
}
}
ll res = 0;
for(i = 0;i<=r-l;i++)
{
if(a[i]!=1) sum[i] = sum[i]*(k+1)%mod; //分解之後,若不是1,一定是個大素數;
res = (res+sum[i])%mod;
}
printf("%lld\n",res);
}
return 0;
}