UVA 618 - Doing Windows(数论)

题目链接:618 - Doing Windows

题意:给定一个大小不能变的屏幕,和四个大小可以变的窗口,变化要保持长宽比,问这四个窗口能不能调整后全部放下正好填满屏幕,不能重叠

思路:情况一共就几种:4个叠一起,3个叠一起+一个,2个和2个,一个和两个叠一起在一个,把这几种情况全判断了就可以了,判断过程利用gcd,lcm可以求边长。

代码:

#include <stdio.h>
#include <string.h>

long long gcd(long long a, long long b) {
    if (b == 0)
	return a;
    return gcd(b, a % b);
}

long long lcm(long long a, long long b) {
    return a / gcd(a, b) * b;
}

struct Win {
    long long x, y;
    bool scanf_() {
	scanf("%lld%lld", &x, &y);
	if (x == 0 || y == 0)
	    return false;
	long long t = gcd(x, y); x /= t; y /= t;
	return true;
    }
    void swap() {
	long long t = x;
	x = y;
	y = t;
    }
} win, w[4];

bool check1(Win a, Win b, Win c, Win d) {
    long long sum = 0;
    if (win.y % a.y)
	return false;
    sum += win.y / a.y * a.x;
    if (win.y % b.y)
	return false;
    sum += win.y / b.y * b.x;
    if (win.y % c.y)
	return false;
    sum += win.y / c.y * c.x;
    if (win.y % d.y)
	return false;
    sum += win.y / d.y * d.x;
    if (sum != win.x)
	return false;
    return true;
}

bool check(Win a, Win b, Win c, long long wx, long long wy) {
    if (wy <= wx / a.x * a.y) return false;
    long long yy = wy - wx / a.x * a.y;
    long long sum = 0;
    if (yy % b.y) return false;
    sum += yy / b.y * b.x;
    if (yy % c.y) return false;
    sum += yy / c.y * c.x;
    if (sum != wx) return false;
    return true;
}

bool judge3(Win a, Win b, Win c, long long wx, long long wy) {
    if (check(a, b, c, wx, wy)
	    || check(b, a, c, wx, wy)
	    || check(c, a, b, wx, wy)) return true;
    return false;
}

bool judge2(Win a, Win b, Win c, long long wx, long long wy) {
    if (judge3(a, b, c, wx, wy))
	return true;
    a.swap();
    b.swap();
    c.swap();
    if (judge3(a, b, c, wy, wx))
	return true;
    return false;
}

bool check2(Win a, Win b, Win c, Win d) {
    long long sum = 0;
    if (win.x % d.x)
	return false;
    long long wy = win.x / d.x * d.y;
    if (wy >= win.y)
	return false;
    long long yy = win.y - wy;
    if (judge2(a, b, c, win.x, yy))
	return true;
    if (yy % a.y) return false;
    sum += yy / a.y * a.x;
    if (yy % b.y) return false;
    sum += yy / b.y * b.x;
    if (yy % c.y) return false;
    sum += yy / c.y * c.x;
    int flag = 0;
    if (sum == win.x) flag = 1;
    return flag;
}

bool check3(Win a, Win b, Win c, Win d) {
    long long sum = 0;
    long long wy = lcm(a.y, b.y);
    if (wy >= win.y)
	return false;
    sum += wy / a.y * a.x;
    sum += wy / b.y * b.x;
    if (win.x % sum)
	return false;
    if (win.y <= win.x / sum * wy)
	return false;
    long long yy = win.y - win.x / sum * wy;
    sum = 0;
    if (yy % c.y)
       	return false;
    sum += yy / c.y * c.x;
    if (yy % d.y)
	return false;
    sum += yy / d.y * d.x;
    if (win.x != sum)
	return false;
    return true;
}

bool judge() {
    if (check1(w[0], w[1], w[2], w[3]))
	return true;
    if (check2(w[0], w[1], w[2], w[3])
	    || check2(w[0], w[1], w[3], w[2])
	    || check2(w[0], w[3], w[2], w[1])
	    || check2(w[3], w[1], w[2], w[0]))
       	return true;
    if (check3(w[0], w[1], w[2], w[3])
	    || check3(w[0], w[2], w[1], w[3])
	    || check3(w[0], w[3], w[1], w[2]))
	return true;
    return false;
}

bool solve() {
    if (judge())
	return true;
    win.swap();
    for (long long i = 0; i < 4; i++)
	w[i].swap();
    if (judge())
	return true;
    return false;
}

int main() {
    long long cas = 0;
    while (~scanf("%lld%lld", &win.x, &win.y) && win.x || win.y) {
	for (long long i = 0; i < 4; i++)
	    w[i].scanf_();
	printf("Set %lld: %s\n", ++cas, solve()? "Yes":"No");
    }
    return 0;
}

UVA 618 - Doing Windows(数论),码迷,mamicode.com

时间: 2024-08-12 07:24:15

UVA 618 - Doing Windows(数论)的相关文章

uva 618 - Doing Windows(暴力+数学)

题目链接:uva 618 - Doing Windows 题目大意:给出电脑桌面的大小W和H,现在在桌面上有4个窗口,给出窗口的初始大小,问说能不能通过调整各个窗口的大小(长宽比例不能变)使得4个屏幕刚好占满整个屏幕,并且互相不覆盖. 解题思路:其实可以直接暴力出所有情况,不过细节比较多,而且要考虑所有的细节. 我的做法的是先将4个窗口缩小至最小的状态,然后枚举左下角的窗口, 有四种可能 蓝色部分为另外枚举的窗口,3,4种情况要分别保证说长.宽相等,然后S部分就是子问题. 所以用一个二进制数来表

uva 10560 - Minimum Weight(数论)

题目连接:uva 10560 - Minimum Weight 题目大意:给出n,问说至少需要多少个不同重量的砝码才能称量1~n德重量,给出所选的砝码重量,并且给出k,表示有k个重量需要用上述所选的砝码测量. 解题思路:重量为1的砝码肯定要选,它可以表示到1的重量,那么下一个砝码的重量肯定选择3(2?1+1),这样1,3分别可以用一个砝码表示,而2,4分别为3-1和3+1,这样1~4的重量也都可以表示.于是有公式ai=si?1?2+1. #include <cstdio> #include &

uva 11105 - Semi-prime H-numbers(数论)

题目链接:uva 11105 - Semi-prime H-numbers 题目大意:H-number为4?k+1(k为非负数),H-composites为因子中含有H-number(不包括自己本身)的数,反之久是H-prime,给定n,求有多少H-composites. 解题思路:首先用筛选法求出范围内的H-prime,然后枚举两个判断乘积是否在范围内. #include <cstdio> #include <cstring> const int maxn = 1e6+5; ty

UVA 11754 - Code Feat(数论)

UVA 11754 - Code Feat 题目链接 题意:给定一个c个x, y1,y2,y3..yk形式,前s小的答案满足s % x在集合y1, y2, y3 ... yk中 思路:LRJ大白例题,分两种情况讨论 1.所有x之积较小时候,暴力枚举每个集合选哪个y,然后中国剩余定理求解 2.所有x之积较大时候,选定一个k/x尽可能小的序列,枚举x * t + y (t = 1, 2, 3...)去暴力求解. 代码: #include <stdio.h> #include <string.

UVA 718 - Skyscraper Floors(数论)

UVA 718 - Skyscraper Floors 题目链接 题意:在一个f层高的楼上,有e个电梯,每个电梯有x,y表示y + k * x层都可以到,现在要问从a层能否到达b层(中间怎么换乘电梯不限制) 思路:对于两个电梯间能不能换乘,只要满足y[i] + xx x[i] == y[j] + yy y[j].然后移项一下,就可以用拓展欧几里得求解,进而求出x,y的通解,然后利用通解范围x' >= 0, y' >= 0, x[i] x' + y[i] <= f, x[j] y' + y

UVA 10692 - Huge Mods(数论)

UVA 10692 - Huge Mods 题目链接 题意:求a0a1a2...mod m 思路:直接算肯定不行,利用欧拉定理ab=a(b mod phi(m) + phi(m))(b>=phi(m)),对指数进行降值处理,然后就可以利用快速幂去计算了,计算过程利用递归求解. 代码: #include <stdio.h> #include <string.h> const int N = 1005; int phi[N * 10], vis[N * 10], m, n, a[

uva 718 - Skyscraper Floors(数论+bfs)

题目链接:uva 718 - Skyscraper Floors 题目大意:一栋大楼,有F层楼,E个电梯,现在要从A层到B层,问是否可行,每个电梯给出Xi和Yi,代表这个电梯可以到达的层数Yi+k?Xi(k≥0) 解题思路:建图,以A,B以及电梯为节点建图,将可以到达A,B这两层的电梯与这两点建边,在将两两电梯可以达到同一层的建边,判断方法为:Yi+aXi=Yj+bXj,移项得:aXi+bXj=Yj?Yi,即是一个线性方程,用拓展欧几里得算法求出通解的形式,判断是否存在通解在0~F之间即可. #

UVA 10623 - Thinking Backward(数论)

UVA 10623 - Thinking Backward 题目链接 题意:给定一个数量,求用圆,椭圆,三角形分割平面,分割出该数量,输出所有情况 思路:有公式2 + 2m(m-1) + n(n-1) + 4mn + 3p(p-1) + 6mp + 6np 由于m和p都是[0,100],所以可以枚举m和p,去求出n,然后判断合不合适 代码: #include <stdio.h> #include <string.h> #include <math.h> #include

uva 11728 - Alternate Task(数论)

题目链接:uva 11728 - Alternate Task 题目大意:给出S,求N,要求N所有的因子和为S. 解题思路:枚举因子i,所有整除i的数和加上i. #include <cstdio> #include <cstring> const int N = 1005; int n, c[N], v[N]; void init () { memset(c, 0, sizeof(c)); memset(v, -1, sizeof(v)); for (int i = 1; i &l