CF1499D The Number of Pairs
阿新 • • 發佈:2021-12-16
題目大意
有 \(T\) 組詢問,每組詢問給定三個整數 \(c,d,x\)
問有多少對 \((a,b)\) 使得 \(c\times \operatorname{lcm}(a,b) - d\times \gcd(a , b) = x\)
\(c,d,x\le 10^7\)。
題目分析
直接列舉複雜度直接爆炸,考慮化式子:
\[\operatorname{lcm}(a,b)=\dfrac{x+d\times \gcd(a,b)}{c} \]顯然 \(\operatorname{lcm}(a,b)\) 一定為 \(\gcd(a,b)\),所以不妨設 \(\operatorname{lcm}(a,b)=r\times \gcd(a,b)\)
於是有:
\[r\times \gcd(a,b)=\dfrac{x+d\times\gcd(a,b)}{c} \]\[r=\dfrac{\frac{x}{\gcd(a,b)}+d}{c} \]\[r\times c-d=\dfrac{x}{\gcd(a,b)} \]所以有:
\[\gcd(a,b)=\dfrac{x}{r\times c-d} \]\(\gcd(a,b)\) 一定是正整數,所以 \((r\times c-d)|x\)。
\(c,d,x\) 已給出,列舉 \(r\) 即可。
\(c,d,x\) 的資料範圍都很大,為 \(1e7\),可以想到什麼?
馬上想到埃氏篩/尤拉篩。
尤拉篩時,我們還可以順便處理出 \(sum_i\)
若 \(i\) 是質數,則 \(sum_i\) 一定為 \(1\)。
其他情況正常判斷即可。
考慮一下:現在知道 \(i\) 是 \(x\) 的一個因數,我們可以幹什麼?
若 \(i\) 能被表示成 \(r\times c-d\) 的形式,那麼此時方案數為 \(2^{sum_r}\);否則為 \(0\)。
其中,\(r\gets \dfrac{d+i}{c}\)。
還要考慮一點:若當前列舉的 \(r\) 的平方並不等於 \(x\),則再加上 \(\dfrac{x}{i}\) 對答案的貢獻。
可以讓這一步的時間複雜度變為 \(O(\sqrt{x})\)。
於是這道題就做完了。
程式碼
雖然碼風比較奇怪,但是感覺思路比較清晰qwq。
const int ma=2e7+5;
int p[ma],sum[ma];//sum[i]:i 的質因子個數
bool is[ma];
int T,c,d,x;
int idx;
inline void init(int R)
{
is[1]=true;
for(register int i=2;i<R;i++)
{
if(is[i]==false)
{
p[++idx]=i;
sum[i]=1;
}
for(register int j=1;j<=idx && i*p[j]<R;j++)
{
is[i*p[j]]=true;
sum[i*p[j]]=sum[i]+1;
if(i%p[j]==0)
{
sum[i*p[j]]=sum[i];
break;
}
}
}
}
inline int calc(int now)
{
if((d+now)%c!=0)
{
return 0;
}
int r=(d+now)/c;
return 1ll<<sum[r];
}
#undef int
int main(void)
{
#define int long long
init(ma);
T=read();
while(T--)
{
c=read(),d=read(),x=read();
int ans(0);
for(register int i=1;i*i<=x;i++)
{
if(x%i==0)
{
ans+=calc(i);
if(i*i!=x)
{
ans+=calc(x/i);
}
}
}
printf("%lld\n",ans);
}
return 0;
}