Codeforces Round #489 (Div. 2) B. Nastya Studies Informatics
题意:给出一个范围 l,r,两个数x,y。要求在【l,r】,找出一对a,b。使得gcd(a,b)=x,lcm(a,b)=y。问能找到多少对这样的数。
题解:如果用a*b=x*y,肯定会超时。我们设a=n*x,b=x*m;就有,y=n*m*x,a*b=n*m*m*x;这样得出,y必定整除x。已经gcd(a,b)=x,得出,gcd(a/x,b/x)=1->gcd(n,m)=1,又y=n*m*x,推出n*m=y/x.;然后直接枚举n,m就行了,细节看代码。
#include <iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<map>
#include<queue>
#include<set>
#include<cmath>
#include<stack>
#include<string>
const int maxn=5e5+10;
const int mod=1e9+7;
const int inf=1e8;
#define me(a,b) memset(a,b,sizeof(a))
#define lowbit(x) x&(-x)
typedef long long ll;
using namespace std;
int gcd(int a,int b)
{
return b==0?a:gcd(b,a%b);
}
int main()
{
int l,r,x,y;
cin>>l>>r>>x>>y;
if(y%x!=0)
cout<<"0"<<endl;
else
{
int num=y/x,ans=0;
for(int i=1;i*i<=num;i++)//枚举到根号num就行了,每次+2,特判n==m的情况。
{
int j=num/i;
if(num%i==0&&gcd(i,j)==1&&l<=i*x&&i*x<=r&&l<=j*x&&j*x<=r)
i==j?ans++:ans+=2;
}
cout<<ans<<endl;
}
return 0;
}
2019长安大学ACM校赛-LCM
题意:给出两个正整数n和c。 找到一对正整数(a,b),它满足a和b都不超过n,它们的最小公倍数是c。 而且,最大化 a×b的值。 如果a和b不存在,则打印-1,否则打印a*b的最大值。
题解:现在我们设gcd(a,b)=x,a=p*x,b=q*x,就能得出,a*b=c*x,p*q*x=c;最后得出:p*q=c/x;
现在x为a,b的最大公约数,x又为c的因子,通过:a*b=c*x,可以得出当x越大,a*b的乘积越大,所以我们可以从大到小枚举c的因子,找到就结束循环(一个小小的优化)。
注意:这里1也要算在c的因子里进行枚举,因为gcd(a,b)可能等于1。
#include <iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<map>
#include<queue>
#include<set>
#include<cmath>
#include<stack>
#include<string>
const int mod = 998244353;
const int maxn = 1e3 + 5;
const int inf = 1e9;
const long long onf = 1e18;
#define me(a, b) memset(a,b,sizeof(a))
#define lowbit(x) x&(-x)
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define PI 3.14159265358979323846
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
ll gcd(ll a, ll b) {
if (!b)
return a;
return gcd(b, a % b);
}
bool cmp(int x, int y) {
return x > y;
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
ll n, c;
scanf("%lld%lld", &n, &c);
ll cnt[maxn], len = 0;
for (int i = 1; i * i <= c; i++) {
if (c % i == 0) {
cnt[len++] = i;
if (c / i != i)
cnt[len++] = c / i;
}
}
if (len == 0 && n < c)
printf("-1\n");
else {
ll ans = -1;
sort(cnt, cnt + len, cmp);
bool flag = 1;
for (int i = 0; i < len && flag; i++) {
ll temp = c / cnt[i];
for (ll j = 1; j <= n && j * j <= temp && flag; j++) {
if (temp % j == 0 && temp / j * cnt[i] <= n && j * cnt[i] <= n && gcd(temp / j, j) == 1) {
ans = max(ans, temp * cnt[i] * cnt[i]);
flag = 0;
}
}
}
printf("%lld\n", ans);
}
}
return 0;
}