给定4个数,a,b,c,d,问是否存在两个数x,y, a < x < = c , b < y < = d a
由于x * y需要包含a * b所有的因数,且x,y还要在一定的范围内,则可以先保证一个数x1在合法位置内,然后通过 a ∗ b / g c d ( a ∗ b , x 1 ) a*b/gcd(a*b,x1) a∗b/gcd(a∗b,x1)获得一个包含a * b剩余因子的数s,然后再将其扩大为比d小的数,在检查是否比b大即可。
#include
#define x first
#define y second
#define C(i) str[0][i]!=str[1][i]
using namespace std;
typedef unsigned long long ULL;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
const int N =2e5+10, Mod = 998244353, P = 2048;
void solve() {
LL a,b,c,d;
cin >>a >>b >>c >>d;
for(LL i=a+1;i<=c;i++){
LL s=a*b/(__gcd(a*b,i));
LL x=d/s*s;
if(x>b){
cout <<i <<" " <<x <<"\n";
return ;
}
}
cout <<-1 <<" " <<-1 <<"\n";
}
int main() {
int t = 1;
cin >> t;
while (t--) solve();
return 0;
}
给定4个数,a,b,c,d,问是否存在两个数x,y, a < x < = c , b < y < = d a
由于整数的范围扩大,若枚举a+1到c会超时。简单版本中通过 a ∗ b / g c d ( a ∗ b , x 1 ) a*b/gcd(a*b,x1) a∗b/gcd(a∗b,x1)获得一个包含a * b剩余因子的数s,实际上是通过枚举x1得到a * b的一个因子,然后获得另一个因子,然后再放大另外一个因子得到符合范围的数。则实际上我们是要获得a * b的因数。
由于a*b的因数是由a的因数乘b的因数得到的,则可以先得到a,b的因数,然后枚举两个因数的乘积从而得到a * b的因数。然后再像简单版本中的做法类似,将两个因数放大到合法范围。由于1e18内的数,最多有103680个因数,1e9内的数最多有1344个因数。则时间复杂度为O( a + b + ( 1344 ) 2 \sqrt{a}+\sqrt{b}+(1344)^2 a+b+(1344)2)
#include
#define x first
#define y second
#define C(i) str[0][i]!=str[1][i]
using namespace std;
typedef unsigned long long ULL;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
const int N = 2e5 + 10, Mod = 998244353, P = 2048;
void solve() {
LL a, b, c, d;
cin >> a >> b >> c >> d;
vector<LL> v1, v2;
///获得a,b的因数
for (int i = 1; i <= a / i; i++) {
if (a % i == 0) {
v1.push_back(i),v1.push_back(a / i);
}
}
for (int i = 1; i <= b / i; i++) {
if (b % i == 0) {
v2.push_back(i),v2.push_back(b / i);
}
}
for (auto i : v1) {
for (auto j : v2) {
///获得a*b的两个因数,然后将其放大到合法的范围
LL x = i * j,y=a*b/x;
x*=c/x;
y*=d/y;
if(x>a&&y>b){
cout <<x <<" " <<y <<"\n";
return ;
}
}
}
cout << -1 << " " << -1 << "\n";
}
int main() {
int t = 1;
cin >> t;
while (t--) solve();
return 0;
}
由于a*b的因数是由a的部分质数乘b的部分质数得到的,则可以先得到a,b的各个质数,然后通过DFS分配各个质数的数量,从而得到a * b的两个因数。然后再像简单版本中的做法类似,将两个因数放大到合法范围。1e18的数质数组合能产生的因数数量大概为1e5,故不会超时。
#include
#define x first
#define y second
#define C(i) str[0][i]!=str[1][i]
using namespace std;
typedef unsigned long long ULL;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
const int N = 2e5 + 10, Mod = 998244353, P = 2048;
LL a,b,c,d;
map<int,int> mp;
vector<PII> primes;
void divide(int n){
for(int i=2;i<=n/i;i++){
while(n%i==0) mp[i]++,n/=i;
}
if(n>1) mp[n]++;
}
bool dfs(int u,LL x,LL y){
if(u==primes.size()){
x*=c/x;
y*=d/y;
if(x>a&&y>b){
cout <<x <<" " <<y <<"\n";
return true;
}else return false;
}
///分配当前质数的数量到两个因数当中
int p=primes[u].x,cnt=primes[u].y;
for(int i=1;i<=cnt;i++) y*=p;
for(int i=0;i<=cnt;i++){
if(dfs(u+1,x,y)) return true;
x*=p,y/=p;
}
return false;
}
void solve() {
mp.clear(),primes.clear();
cin >>a >>b >>c >>d;
///先得到a,b的各个质数数量
divide(a),divide(b);
for(auto v:mp) primes.push_back(v);
if(!dfs(0,1,1)) cout <<-1 <<" " <<-1 <<'\n';
}
int main() {
int t = 1;
cin >> t;
while (t--) solve();
return 0;
}