codeforces 1058 D. Vasya and Triangle(已知面积求整数点坐标,规律,利用__gcd把一个数拆成有范围限制的两个数相乘)

版权声明:本文为博主原创文章,转载请注明出处~~ https://blog.csdn.net/hxc2101/article/details/82828750

题目:http://codeforces.com/contest/1058/problem/D

题意:给出横坐标最大值n,纵坐标最大值m,再给出一个k要求,输出三个整数点坐标构成的三角形的面积为m*n/k

思路: (ps:利用__gcd把一个数拆成有范围限制的两个数相乘,不是对这个数的质因数贪心得去乘,凑那两个范围(这样不行的) )

S=\frac{1}{2}\cdot\begin{vmatrix} x_{1}\ y_{1}\1\\ x_{2}\ y_{2}\1\\ x_{3}\ y_{3}\1\\ \end{vmatrix}=\frac{1}{2}\cdot (x_{1}y_{2}+x_{2}y_{3}+x_{3}y_{1}-x_{1}y_{3}-x_{2}y_{1}-x_{3}y_{2})

令x1=y1=0 ,显然 每个三角形的都可以平移到以原点为顶点的三角形

S=\frac{1}{2}\cdot (x_{2}y_{3}-x_{3}y_{2}) = \frac{mn}{k}  即 2S=x_{2}y_{3}-x_{3}y_{2} = \frac{2mn}{k}

因为 x2,y3,x3,y2 都是整数 所以 上式2*S的结果也必定是整数,即2mn必定整除k

1.规律:若三角形的三个点的坐标均为整数点,他的面积S*2必定是整数

2.那么就可以把这个三角形看为是直角三角形了,三点坐标为(0,0) (x,0) (0,y),面积 S=x*y/2 = m*n/k 即可

3.也所以 m*n 不能整除 k 的必定是输出 "NO" 了

4.题目就变成了 把一个整数拆成 两个数(一个<n,一个<m)的乘积  即 x\cdot y=\frac{2mn}{k} 或 \frac{mn}{\tfrac{k}{2}}

显然 k(或 \tfrac{k}{2} ) 的所有质因数 全部都包含在 m的质因数 "并" n的质因数 中

所以

当k为偶数时:k=k/2;   x=n/__gcd(n,k);   k=k/__gcd(n,k);   y=m/__gcd(m,k);   (此时 必定保证了 x<=n&&y<=m,同时等式右边的分母也被除成了1)【利用__gcd把一个数拆成有范围的两个数相乘】

当k为奇数时:x=n/__gcd(n,k);   k=k/__gcd(n,k);   y=m/__gcd(m,k);  和k偶数不同,分子2是没有除下来的,所以需要看若2x<n,则x=2x,否则y=2y    (证明:k奇数,所以k>=3,若前面出现了__gcd(n,k)=1,即x=n,那么必定y<m/3,即2*y必定<m;若前面没有出现过__gcd=1,因为奇数,肯定不会出现__gcd=2,所以最小的也是__gcd=3了,那么显然x<=n/3&&y<=m/3,所以任一个*2都不会超过n或m的,所以前面的那种做法是必定有可行解的)

#include <bits/stdc++.h>
//#pragma GCC optimize(3)
//#pragma GCC optimize("unroll-loops")
//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define pb push_back
#define mkp(a,b) make_pair(a,b)
#define PII pair<int,int>
#define PLL pair<ll,ll>
#define fi first
#define se second
#define lc (d<<1) //d*2
#define rc (d<<1|1) //d*2+1
#define eps 1e-9
#define dbg(x) cerr << #x << " = " << x << "\n";
#define mst(a,val) memset(a,val,sizeof(a))
#define stn(a) setprecision(a)//小数总有效位数
#define stfl setiosflags(ios::fixed)//点后位数:cout<<stfl<<stn(a);
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double PI=3.1415926535897932;
const int MAXN=1e5+10;
const ll mod=1e9+7;
ll inline mpow(ll a,ll b){ll ans=1;a%=mod;while(b){if(b&1)ans=(ans*a)%mod;a=(a*a)%mod,b>>=1;}return ans;}
int inline sgn(double x){return (x>-eps)-(x<eps);} //a<b:sgn(a-b)<0
priority_queue<int,vector<int>,greater<int> > qu; //up
priority_queue<int,vector<int>,less<int> > qd; //dn
const int inf = 0x3f3f3f3f; //9
const ll inff = 0x3f3f3f3f3f3f3f3f; //18

ll n,m,k;
ll x1,y1,x2,y2,x3,y3;
ll x,y;

int main()
{
    fio;
    cin>>n>>m>>k;
    if((ll)2*n*m%k) {cout<<"NO"<<endl;return 0;}
    x1=y1=x2=y3=0;
    int flag=0;
    if(k%2==0) k/=2,flag=1;
    x=n/__gcd(n,k);k/=__gcd(n,k);
    y=m/__gcd(m,k);k/=__gcd(m,k);
    if(!flag)
    {
        if(x*2<n) x*=2;
        else if(y*2<m) y*=2;
    }
    x3=x;y2=y;
    cout<<"YES"<<endl;
    cout<<x1<<" "<<y1<<endl;
    cout<<x2<<" "<<y2<<endl;
    cout<<x3<<" "<<y3<<endl;
}

猜你喜欢

转载自blog.csdn.net/hxc2101/article/details/82828750