1. 程式人生 > >codeforces 1058 D. Vasya and Triangle(已知面積求整數點座標,規律,利用__gcd把一個數拆成有範圍限制的兩個數相乘)

codeforces 1058 D. Vasya and Triangle(已知面積求整數點座標,規律,利用__gcd把一個數拆成有範圍限制的兩個數相乘)

題意:給出橫座標最大值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;
}