@[TOC]([呱一题] 爷奖国方程(数论))
原题
2000ms 256MB
Description
众所周知,时间复杂度为O(
1
N
\frac{1}{N}
N1?)的算法是不可能的,但是国奖爷就爱挑战不可能!现在国奖爷想发明一种时间复杂度为O(
1
N
+
1
M
\frac{1}{N}+\frac{1}{M}
N1?+M1?)的图论算法,并命名为“国奖爷算法”,但是他触碰到了瓶颈。现在,他已经发明了复杂度为O(
1
1
N
+
1
M
\frac{1}{\frac{1}{N}+\frac{1}{M}}
N1?+M1?1?)的算法,并命名为“爷奖国算法”,为了让他的研究更近一步,他需要求解一个“爷奖国方程”,即:
1
1
N
+
1
M
=
T
!
\frac{1}{\frac{1}{N}+\frac{1}{M}}=T!
N1?+M1?1?=T!
其中,
T
!
=
∏
i
=
1
T
i
T!=\prod_{i=1}^T i
T!=∏i=1T?i
由于国奖爷实在是太厉害了,所以你只需要帮国奖爷精确算出这个“爷奖国方程”有多少对正整数解,国奖爷就能通过海量脑细胞精确算出每一组解,你能帮国奖爷挑战不可能吗?注意,(1,2)和(2,1)算两对解。
Input Description
输入一行一个正整数
T
T
T,含义由题目给出。其中
1
≤
T
≤
1
0
7
1\leq T\leq10^7
1≤T≤107
Output Description
输出一行一个正整数
a
n
s
w
e
r
answer
answer,由于答案可能比较大,你只需要输出
a
n
s
w
e
r
m
o
d
19260817
answer\enspace mod\enspace 19260817
answermod19260817。
Input Sample 1
1
Output Sample 1
1
Input Sample 2
2
Output Sample 2
3
Hint
在样例1中,对于T=1,T!=1,有解(2,2)。
在样例2中,对于T=2,T!=2,有解(3,6),(4,4),(6,3)。
题解
我们不妨设
K
=
T
!
K=T!
K=T!,那么有:
1
1
N
+
1
M
=
K
?
1
N
+
1
M
=
1
K
?
(
N
+
M
)
K
=
N
M
?
?
(
N
+
M
)
K
+
N
M
=
0
?
K
2
?
(
N
+
M
)
K
+
N
M
=
K
2
?
(
N
?
K
)
(
M
?
K
)
=
K
2
\frac{1}{\frac{1}{N}+\frac{1}{M}}=K\\ \\ \Leftrightarrow \frac{1}{N}+\frac{1}{M}=\frac{1}{K}\\ \\ \Leftrightarrow (N+M)K=NM\\ \\ \Leftrightarrow -(N+M)K+NM=0\\ \\ \Leftrightarrow K^2-(N+M)K+NM=K^2\\ \\ \Leftrightarrow (N-K)(M-K)=K^2\\
N1?+M1?1?=K?N1?+M1?=K1??(N+M)K=NM??(N+M)K+NM=0?K2?(N+M)K+NM=K2?(N?K)(M?K)=K2
显然,
(
N
?
K
)
,
(
M
?
K
)
(N-K),(M-K)
(N?K),(M?K)为
K
2
K^2
K2的两个因子,所以答案即为
K
2
K^2
K2的因子个数,即
(
T
!
)
2
{(T!)}^2
(T!)2的因子个数。
我们对
T
!
T!
T!做质因子分解,有:
T
!
=
p
1
k
1
?
p
2
k
2
?
p
n
k
n
(
T
!
)
2
=
p
1
2
k
1
?
p
2
2
k
2
?
p
n
2
k
n
T!=p_1^{k_1} \cdot p_2^{k_2} \cdots p_n^{k_n}\\ (T!)^2=p_1^{2k_1} \cdot p_2^{2k_2} \cdots p_n^{2k_n}\\
T!=p1k1???p2k2???pnkn??(T!)2=p12k1???p22k2???pn2kn??
那么
(
T
!
)
2
(T!)^2
(T!)2的因子个数为:
a
n
s
w
e
r
=
(
2
k
1
+
1
)
?
(
2
k
1
+
1
)
?
(
2
k
n
+
1
)
answer=(2k_1+1) \cdot (2k_1+1) \cdots (2k_n+1)\\
answer=(2k1?+1)?(2k1?+1)?(2kn?+1)
现在我们考虑如何对
T
!
T!
T!做质因子分解,对于一个质数
X
X
X,在
[
1
,
T
]
[1,T]
[1,T]中,有
?
T
X
?
\lfloor \frac{T}{X} \rfloor
?XT??个数含有至少1个这个质因子,有
?
T
X
2
?
\lfloor \frac{T}{X^2} \rfloor
?X2T??个数含有至少2个这个质因子……
所以我们只需要先筛出T以内的质数,再对每个质数做上述处理计算T!中含有多少个这个质因子即可。
代码实现
首先,我们要筛出所有的质数,这里用线性筛法。
const int N=1e7+1;
const int M=19260817;
vector<int> prime;
bool notPrime[N];
void filte()
{
for(int i=2;i<N;i++)
{
if(!notPrime[i])
{
prime.push_back(i);
for(long long j=1ll*i*i;j<N;j+=i)
{
notPrime[j]=true;
}
}
}
}
然后,我们对每个质数计算
T
!
T!
T!包含多少个因子。
long long LTZ_euqition(long long T)
{
long long answer=1;
int cnt=0;
for(int X:prime)
{
if(X>T)break;
long long x=X;
while(x<=T)
{
cnt+=T/x;
x*=X;
}
answer*=(2*cnt+1);
answer%=M;
cnt=0;
}
return answer;
}
下附完整实现
#include <iostream>
#include <vector>
using namespace std;
const int N=1e7+1;
const int M=19260817;
vector<int> prime;
bool notPrime[N];
void filte()
{
for(int i=2;i<N;i++)
{
if(!notPrime[i])
{
prime.push_back(i);
for(long long j=1ll*i*i;j<N;j+=i)
{
notPrime[j]=true;
}
}
}
}
long long LTZ_euqition(long long T)
{
long long answer=1;
int cnt=0;
for(int X:prime)
{
if(X>T)break;
long long x=X;
while(x<=T)
{
cnt+=T/x;
x*=X;
}
answer*=(2*cnt+1);
answer%=M;
cnt=0;
}
return answer;
}
int main()
{
filte();
int T;
cin>>T;
cout<<LTZ_euqition(T);
}
|