Technocup 2019 - Elimination Round 1 D. Vasya and Triangle

地址: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
using namespace std;
typedef long long LL;
const int inf = 0x3f3f3f3f;

vectorve;
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
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;
}

你可能感兴趣的:(ACM__数论,ACM__构造)