20180520模拟赛T1——math

【问题描述】

小美有 n 个点 m 条边。

让你给每个点一个正整数编号。

每条边有两个属性,相连的两个点的编号的 GCD 和 LCM。

题目保证整张图连通。

让你构造出一个编号。

【输入格式】

从文件 math.in 中读入数据。

第一行两个正整数 n 和 m。

接下去m行每行 4 个正整数 xi,yi,gcdi,lcmi。

【输出格式】

输出到文件 math.out 中。

如果是有解:

第一行一行 YES。

第二行 n 个数字表示编号。

否则输出一行NO。

【样例】

【样例输入】

1 0

【样例输出】

YES 1

【样例输入】

2 1
1 2 1 3

【样例输出】

YES 1 3

【样例输入】

3 2
3 2 1 2
3 1 1 10

【样例输出】

YES 5 1 2

【样例输入】

2 1
1 2 3 7

【样例输出】

NO

【数据规模】

对于\(100\%\)的数据\(2\le n \le 100,n-1 \le m \le n*(n-1)/2,1\le gcdi, lcmi \le 10^6\)。

题解

这题其实就是一道暴力题,是根据\([a, b] \times (a, b) = a\times b\)。已知\(a\times b\),暴力枚举\(a\),然后把整张图dfs一遍判断其正确性即可。

不得不说:大力出奇迹!

另外,记得开long long。

题目加强版:CF 60C

代码

#include <cctype>
#include <cstdio>
#include <cstring>

typedef long long LL;
#define int long long

#define dd c = getchar()
inline void read(int& x)
{
    x = 0;
    char dd;
    bool f = false;
    for(; !isdigit(c); dd)
        if(c == '-')
            x = -x;
    for(; isdigit(c); dd)
        x = (x<<1) + (x<<3) + (c^48);
    if(f) x = -x;
}
#undef dd

inline int gcd(int __n, int __m)
{
    while (__n)
    {
        int __t = __m % __n;
        __m = __n;
        __n = __t;
    }
    return __m;
}

const int maxn = 105;

int n, m;

int ans[maxn];

struct edge
{
    LL cheng;
    int t;
    int ne;
    int gcdd;
} e[maxn*maxn];

int first[maxn];
bool vis[maxn];

int mm;
inline void add_edge(int f, int t, LL cheng, int gcdd)
{
    e[++mm].ne = first[f];
    e[mm].t = t;
    e[mm].cheng = cheng;
    e[mm].gcdd = gcdd;
    first[f] = mm;

    e[++mm].ne = first[t];
    e[mm].t = f;
    e[mm].cheng = cheng;
    e[mm].gcdd = gcdd;
    first[t] = mm;
}

inline bool dfs(int n, int last)//dfs检验答案正确性
{
    vis[n] = true;
    for(int i = first[n]; i; i = e[i].ne)
    {
        int to = e[i].t;
        if(to == last) continue;
        if(vis[to])
        {
            if((ans[to]*ans[n] != e[i].cheng) || (gcd(ans[to], ans[n]) != e[i].gcdd))
                return false;
        }
        else
        {
            ans[to] = e[i].cheng / ans[n];
            if(gcd(ans[to], ans[n]) != e[i].gcdd)
                return false;
            if(!dfs(to, n))
                return false;
        }
    }
    return true;
}

inline void print()
{
    puts("YES");
    for(int i = 1; i <= n; ++i)
        printf("%lld ", ans[i]);
}

inline void search()
{
    vis[1] = true;
    if(!first[1])
    {
        puts("NO");
        return;
    }
    LL k = e[first[1]].cheng;
    for(int i = 1; i*i <= k; ++i)//暴力枚举所有可能情况
        if(!(k%i))
        {
            ans[1] = i;
            memset(vis, 0, sizeof(vis));
            if(dfs(1, 0))
            {
                print();
                return;
            }
            ans[1] = k/i;
            memset(vis, 0, sizeof(vis));
            if(dfs(1, 0))
            {
                print();
                return;
            }
        }
    puts("NO");
}

signed main()
{
    freopen("math.in", "r", stdin);
    freopen("math.out", "w", stdout);
    scanf("%lld%lld", &n, &m);
    if(n == 1)
    {
        puts("YES\n1");
        return 0;
    }
    for(int i = 1; i <= m; ++i)
    {
        int f, t, gcdd, lcmm;
        read(f), read(t), read(gcdd), read(lcmm);
        add_edge(f, t, (LL)(gcdd*lcmm), gcdd);
    }
    search();
    return 0;
}

原文地址:https://www.cnblogs.com/pfypfy/p/9064226.html

时间: 2024-08-01 02:00:33

20180520模拟赛T1——math的相关文章

20180520模拟赛T3——chess

[问题描述] 小美很喜欢下象棋. 而且她特别喜欢象棋中的马. 她觉得马的跳跃方式很独特.(以日字格的方式跳跃) 小芳给了小美一张很大的棋盘,这个棋盘是一个无穷的笛卡尔坐标. 一开始\(time=0\)的时候,马在原点.每个时刻马都跳一步. 可是这个坐标图有点残缺,有几个点是不能跳到的. 然后小美很好奇在\(time=[0,K]\)中,马能跳到多少个不同的格子. [输入格式] 从文件chess.in中读入数据. 第一行两个数K,n表示时间上限和残缺的点的数量. 接下来n行,每行一个坐标 xi,yi

20180610模拟赛T1——脱离地牢

Description 在一个神秘的国度里,年轻的王子Paris与美丽的公主Helen在一起过着幸福的生活.他们都随身带有一块带磁性的阴阳魔法石,身居地狱的魔王Satan早就想着得到这两块石头了,只要把它们溶化,Satan就能吸收其精华大增自己的魔力.于是有一天他趁二人不留意,把他们带到了自己的地牢,分别困在了不同的地方.然后Satan念起了咒语,准备炼狱,界时二人都将葬身于这地牢里. 危险!Paris与Helen都知道了Satan的意图,他们要怎样才能打败魔王,脱离地牢呢?Paris想起了父王

2017 11 6模拟赛T1

作为一个毒瘤出题人(wzy:我不是毒瘤出题人,这些题明明很水的),wzy的题干十分复杂,但是把题意简化之后,相当简单粗暴... 求首项为1,等比为m,项数为t的等比数列的和,答案对k取模 不保证m与k互质 如果m与k互质的话,用等比数列的求和公式在求个逆元就能解决了,但是本题显然不能,于是必须考虑不含有除法的算法 于是就有了分治求等比数列和的办法. 设s(x)为等比数列的第n项 由等比数列的性质得到s(y)=s(x)*m^(y-x) (y>x) 将一个长度为2r的等比数列拆分成登场的两部分,对应

[模拟赛] T1 高级打字机

Description 早苗入手了最新的高级打字机.最新款自然有着与以往不同的功能,那就是它具备撤销功能,厉害吧. 请为这种高级打字机设计一个程序,支持如下3种操作: 1.T x:在文章末尾打下一个小写字母x.(type操作) 2.U x:撤销最后的x次修改操作.(Undo操作) (注意Query操作并不算修改操作) 3.Q x:询问当前文章中第x个字母并输出.(Query操作) 文章一开始可以视为空串. Input 第1行:一个整数n,表示操作数量. 以下n行,每行一个命令.保证输入的命令合法

校内模拟赛T1大美江湖

这就是一个模拟题,注意1234分别对应左右上下横坐标和纵坐标的判断就好了 题解: 需要注意的是,向上取整ceil函数是对于一个double值返回一个double值,也就是说在ceil里面的类型一定要是double,否则会炸 代码: #include<cstdio> #include<iostream> #include<cstdlib> #include<cmath> #include<cstring> #include<string>

【2019.8.15 慈溪模拟赛 T1】插头(plugin)(二分+贪心)

二分 首先,可以发现,最后的答案显然满足可二分性,因此我们可以二分答案. 然后,我们只要贪心,就可以验证了. 贪心 不难发现,肯定会优先选择能提供更多插座的排插,且在确定充电器个数的情况下,肯定选择能经过排插数量最大的那些充电器. 所以,我们只要模拟插排插的过程,记录当前深度\(d\).插座数\(t\)即可. 设选择的能经过排插数量恰好为\(d\)的充电器有\(x\)个,则若\(t<x\),显然不合法. 否则,我们将\(x\)个位置插上充电器,其余位置尽可能地插排插,就可以了. 代码 #incl

[10.5模拟赛]T1

T1 Description 在\(2019\)年,某小朋友刚刚学习了树,非常开心.现在他想解决这样一个问题:给定一颗有根树(根为\(1\)),有以下两种操作: 标记操作:对某个结点打上标记(在最开始,只有结点\(1\)有标记,其他结点均无标记,而且对于某个结点,可以打多次标记.) 询问操作:询问某个结点最近的一个打了标记的祖先(这个结点本身也算自己的祖先) 你能帮帮他吗? Input 输入第一行两个正整数\(N\)和\(Q\)分别表示节点个数和操作次数 接下来\(N-1\)行,每行两个正整数\

2017-9-3模拟赛T1 卡片(card)

题目 [题目描述] lrb 喜欢玩卡牌.他手上现在有n张牌,每张牌的颜色为红绿蓝中的一种.现在他有两种操作.一是可以将两张任意位置的不同色的牌换成一张第三种颜色的牌:二是可以将任意位置的两张相同颜色的牌换成一张该颜色的牌.两个操作后都可以将生成的牌放到任意位置.现在他想知道,最后一张牌可能是什么颜色的. [输入描述] 第一入一个n,表示卡牌数量.第二行输入一个由'B','G','R'组成的长度为n的字符串,分别表示卡牌的颜色为蓝色.绿色.红色中的一种.[输出描述]输出'B','G','R'中的若

洛谷 U360 子矩阵 (NOIP模拟赛T1)题解

题目链接:https://www.luogu.org/problem/show?pid=U360 题目背景 夏令营 题目描述 小A有一个N×M的矩阵,矩阵中1~N*M这(N*M)个整数均出现过一次.现在小A在这个矩阵内选择一个子矩阵,其权值等于这个子矩阵中的所有数的最小值.小A想知道,如果他选择的子矩阵的权值为i(1<=i<=N×M),那么他选择的子矩阵可能有多少种?小A希望知道所有可能的i值对应的结果,但是这些结果太多了,他算不了,因此他向你求助. 输入输出格式 输入格式: 第一行,两个整数