地址:http://codeforces.com/contest/1030/problem/D
思路:因为三个点是整数点, S=(1/2)*(x1y2+x2y3+x3y1-x1y3-x2y1-x3y2) = (n * m) / k;
如果2 * n * m / k是分数的话,那就不存在三个整数点,又因为k >= 2;所以必存在三个点,可以这样构造以原点作直角三角形,三点都在坐标轴上,找两个这样的数x * y = (2 * n * m / k),0 <= x <= n,0 <= y <= m;
注意:我n,m在比赛的时候用的int,到死都没想到爆了,要用long long。。。
我脑子笨,想到一个分解质因子找这两个数的方法,因为遍历找会超时,分解质因子,然后再dfs找这样的数;
886ms
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int inf = 0x3f3f3f3f;
vector<LL>ve;
LL ptr;
LL n,m,k;
bool flag = false;
void dfs(int pos,int num,LL ans)
{
LL x = ptr / ans;
if(flag) return ;
if(ans > n) return ;
if(ans <= n && x > 0 && x <= m){
flag = true;
printf("YES\n");
printf("0 0\n");
printf("%lld 0\n",ans);
printf("0 %lld\n",x);
return ;
}
int len = ve.size();
for(int i = pos + 1;i < len;++i)
{
dfs(i,num + 1,ans * ve[i]);
}
}
int main()
{
scanf("%lld %lld %lld",&n,&m,&k);
LL ans = n * m * 2LL;
//cout << ans << " " << ans % k << endl;
if(ans % k == 0){
LL x = ans / k;
//cout << x << endl;
ptr = x;
for(LL i = 2; i * i <= x; i++)
{
if(x % i == 0)
{
while(x % i == 0) {
x /= i;
ve.push_back(i);
}
}
}
if(x > 1)
ve.push_back(x); //这个不可以缺少
LL res = 1;
int len = ve.size();
//cout << len << endl;
flag = false;
dfs(-1,0,1LL);
//其实这里写不写无所谓,因为永远都能找到
if(!flag){
printf("NO\n");
}
}else{
printf("NO\n");
}
return 0;
}
有个31ms做法,利用n / gcd(n,k),这样就可以快速找到最大的x
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int inf = 0x3f3f3f3f;
LL gcd(LL a,LL b)
{
return (b == 0) ? a : gcd(b,a % b);
}
int main()
{
LL n,m,k;
cin >> n >> m >> k;
LL ans = n * m * 2LL;
if(ans % k != 0){
printf("NO\n");
return 0;
}
ans /= k;
LL ptr = gcd(n,k);
LL a = n / ptr;
LL b = ans / a;
if(b > m){
b /= 2LL;
a *= 2LL;
}
if(b > m){
printf("NO\n");
}
printf("YES\n");
printf("0 0\n%lld 0\n0 %lld\n",a,b);
return 0;
}