10.14 数论
问题 - D - Codeforces — Problem - D - Codeforces
数论。考察gcd,lcm的性质和素数筛。
题意:给定c,d,x。求满足c∗lcm(a,b)−d∗gcd(a,b)=xc*lcm(a,b)−d*gcd(a,b)=xc∗lcm(a,b)−d∗gcd(a,b)=x的ab对数量。
思路:首先发现有lcm和gcd,可以容易想到 a=k1∗gcd(a,b),b=k2∗gcd(a,b)a=k_1*gcd(a,b),b=k_2*gcd(a,b)a=k1∗gcd(a,b),b=k2∗gcd(a,b)。
且k1k_1k1与k2k_2k2互质,因为如果不互质,gcd(a,b)gcd(a,b)gcd(a,b)还要乘上gcd(k1,k2)gcd(k_1,k_2)gcd(k1,k2)。又有lcm(a,b)=a∗b/gcd(a,b)lcm(a,b)=a*b/gcd(a,b)lcm(a,b)=a∗b/gcd(a,b)。
我们带入化简原式得到:
c∗gcd(a,b)∗k1∗k2−d∗gcd(a,b)=xc*\gcd(a,b)*k_1*k_2-d*\gcd(a,b)=x c∗gcd(a,b)∗k1∗k2−d∗gcd(a,b)=x
gcd(a,b)=xc∗k1∗k2−d\gcd(a,b)=\frac{x}{c*k_1*k_2-d} gcd(a,b)=c∗k1∗k2−dx
因为gcd(a,b)gcd(a,b)gcd(a,b)一定是整数,所以(c∗k1∗k2−d)∣x(c*k_1*k_2-d) | x(c∗k1∗k2−d)∣x ,我们令 y=c∗k1∗k2−dy=c*k_1*k_2-dy=c∗k1∗k2−d。
k1∗k2=y+dck_1*k_2=\frac{y+d}{c} k1∗k2=cy+d
因为前面我们已经推导出k1k_1k1与k2k_2k2互质,且题目给了c和d的值,所以我们只需要枚举y。记k为右式。
保证k的每种质因数属于k1k_1k1或k2k_2k2,贡献为2cnt2^{cnt}2cnt,cnt为k的质因子种数。
比如对于样例1,1 1 3。
当y=1,k=2,k1k_1k1 k2k_2k2分别可为1 2;2 1。贡献为2。
当y=2,y不是x的因子,略过。
当y=3,k=4,k1k_1k1 k2k_2k2分别可为1 4;4 1。贡献为2。
注意y和d的上限都是1e7,所以素数筛数组要开到2e7。
int ou[mm]; //计算i的质因子的个数
int prime[mm]; //判断i是否为质数,1为质数
int cnt = 0; //记录质数个数
void oula()
{for (int i = 2; i <= mm; i++){if (!ou[i]){prime[++cnt] = i;ou[i] = 1;}for (int j = 1; i * prime[j] <= mm; j++){ou[i * prime[j]] = ou[i] + 1;if (i % prime[j] == 0) //确保每个合数只被其最小质因数标记一次{ou[i * prime[j]] = ou[i];break;}}}
}void solve()
{int c, d;cin >> c >> d >> x;ans = 0;for (int i = 1; i * i <= x; i++){if (x % i == 0){int y0 = i, y1 = x / i;int k;if ((y0 + d) % c == 0){k = (y0 + d) / c;ans += 1ll << ou[k];}if (y0 == y1){continue;}if ((y1 + d) % c == 0){k = (y1 + d) / c;ans += 1ll << ou[k];}}}cout << ans;
}