problem
思路
满足 pq=n p q = n 且 gcd(p,q)=1 g c d ( p , q ) = 1 的二元组个数是多少呢?
显然是 2w(n) 2 w ( n ) 个,其中 w(n) w ( n ) 是不同的素因子的数目
那么 fr+1(n)=∑uv=nfr(u)+fr(v)2 f r + 1 ( n ) = ∑ u v = n f r ( u ) + f r ( v ) 2 如何计算呢?
fr+1(n)=∑uv=nfr(u)+fr(v)2=∑d|nfr(d) f r + 1 ( n ) = ∑ u v = n f r ( u ) + f r ( v ) 2 = ∑ d | n f r ( d )
由于 r 1e6 r 1 e 6 ,询问又有 1e6 1 e 6 ,那我们不可能暴力搞。
我们知道 fr(n) f r ( n ) 是积性函数 问题转为求解 fr(pk) f r ( p k )
由于 fr(pk)=∑i=ki=0fr−1(pi) f r ( p k ) = ∑ i = 0 i = k f r − 1 ( p i )
由于任意p,k>=1,有 f0(pk)=2 f 0 ( p k ) = 2 ,因此 fr(pk) f r ( p k ) 的值和 p p 无关。预处理所有的组合即可。k是log级别的。
时间复杂度 O(rlogn+T∗(n√log1e3)) O ( r l o g n + T ∗ ( n l o g 1 e 3 ) )
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int maxn=1e6+10;
ll help[maxn][21];// r k 给定时 不同p结果相同
bool valid[1010];
int ans[500];
int tot;
void init()
{
help[0][0]=1;
for(int k=1;k<=20;++k) help[0][k]=2;
for(int r=1;r<=int(1e6);++r){
help[r][0]=help[r-1][0];
for(int k=1;k<=20;++k){
help[r][k]=(help[r][k-1]+help[r-1][k])%mod;
}
}
}
void get_prime(int n)
{
tot=0;
memset(valid,true,sizeof(valid));
for(int i=2;i<=n;++i){
if(valid[i]){
ans[++tot]=i;
}
for(int j=1;ans[j]*i<=n;++j){
valid[ans[j]*i]=false;
if(i%ans[j]==0){
break;
}
}
}
}
int main()
{
int t;
scanf("%d",&t);
//cout<<clock()<<endl;
init();
get_prime(1010);
//cout<<tot<<endl;
//cout<<clock()<<endl;
//cout<<help[1][1]<<" "<<help[1][2]<<endl;
while(t--)
{
int r,n;
scanf("%d%d",&r,&n);
ll res=1;
for(int j=1;ans[j]*ans[j]<=n && j<=tot;++j){
int i=ans[j];
if(n%i==0){
int k=0;
while(n%i==0){
n/=i;
k++;
}
//cout<<i<<" "<<k<<endl;
res=(res*help[r][k])%mod;
}
}
if(n>1){
res=(res*help[r][1])%mod;
//cout<<n<<endl;
}
printf("%lld\n",res);
}
return 0;
}