GDCPC2016题解 by lby@SYSU | Asiimov

本文详细解析了GDCPC2016竞赛中的多个问题,包括ABCD、Bob's magical number、Color等题目,涉及算法思路、时间复杂度分析和代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Problem A. ABCD

题目大意

给出一个四边形四条边 ABCDADBC 及两条对角线 ACBD 的长度,问这个四边形的顶点能否在一个圆上

算法思路

通过余弦定理考察 ACB ADB 是否相等即可。

时间复杂度: O(1)

代码

/**
 * Copyright © 2016 Authors. All rights reserved.
 * 
 * FileName: A.cpp
 * Author: Beiyu Li <sysulby@gmail.com>
 * Date: 2016-05-09
 */
#include <bits/stdc++.h>

using namespace std;

#define rep(i,n) for (int i = 0; i < (n); ++i)
#define For(i,s,t) for (int i = (s); i <= (t); ++i)
#define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)

typedef long long LL;
typedef pair<int, int> Pii;

const int inf = 0x3f3f3f3f;
const LL infLL = 0x3f3f3f3f3f3f3f3fLL;

const double eps = 1e-10;
int sgn(double x) { return x < -eps? -1: x > eps; }

inline double cosf(double a, double b, double c)
{ return (a * a + b * b - c * c) / (2 * a * b); }

int main()
{
        int T, cas = 0;
        scanf("%d", &T);

        while (T--) {
                int ab, cd, ad, bc, ac, bd;
                scanf("%d%d%d%d%d%d", &ab, &cd, &ad, &bc, &ac, &bd);
                printf("Case #%d: %s\n", ++cas, !sgn(cosf(ac, bc, ab)
                                        - cosf(ad, bd, ab))? "Yes": "No");
        }

        return 0;
}

Problem B. Bob’s magical number

题目大意

构造一个 N 个点,每个点度数都为3的无向图

算法思路

N<4 时无解
由于共有 3N2 条边,故 N 为奇数时一定无解
N 为偶数时将所有点连成环,再将对称点连起来即可

时间复杂度: O(N)

代码

/**
 * Copyright © 2016 Authors. All rights reserved.
 * 
 * FileName: B.cpp
 * Author: Beiyu Li <sysulby@gmail.com>
 * Date: 2016-05-09
 */
#include <bits/stdc++.h>

using namespace std;

#define rep(i,n) for (int i = 0; i < (n); ++i)
#define For(i,s,t) for (int i = (s); i <= (t); ++i)
#define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)

typedef long long LL;
typedef pair<int, int> Pii;

const int inf = 0x3f3f3f3f;
const LL infLL = 0x3f3f3f3f3f3f3f3fLL;

int main()
{
        int T, cas = 0;
        scanf("%d", &T);

        while (T--) {
                int n;
                scanf("%d", &n);
                if (n < 4 || (n & 1)) {
                        printf("Case #%d: No\n", ++cas);
                } else {
                        printf("Case #%d: Yes\n", ++cas);
                        For(i,1,n) {
                                printf("%d %d\n", i, i == n? 1: i + 1);
                                if (i <= n / 2) printf("%d %d\n", i, i + n / 2);
                        }
                }
        }

        return 0;
}

Problem C. Color

题目大意

用K种颜色对长度为N的环涂色,问考虑旋转同构下本质不同的涂色方案有多少种

算法思路

由Pólya定理可知,答案等于 i=1Nkgcd(i,N)
对于 d=gcd(i,N) kd 项共有 φ(Nd)
所以上式化简为 d|Nφ(Nd)kd

时间复杂度: O(N)

代码

/**
 * Copyright © 2016 Authors. All rights reserved.
 * 
 * FileName: C.cpp
 * Author: Beiyu Li <sysulby@gmail.com>
 * Date: 2016-05-09
 */
#include <bits/stdc++.h>

using namespace std;

#define rep(i,n) for (int i = 0; i < (n); ++i)
#define For(i,s,t) for (int i = (s); i <= (t); ++i)
#define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)

typedef long long LL;
typedef pair<int, int> Pii;

const int inf = 0x3f3f3f3f;
const LL infLL = 0x3f3f3f3f3f3f3f3fLL;

const int mod = 1000000007;

int n, k, ret;
vector<Pii> fct;

int pow_mod(int a, int b)
{
        int ret = 1;
        for (; b; a = (LL)a * a % mod, b >>= 1)
                if (b & 1) ret = (LL)ret * a % mod;
        return ret;
}

void decomp(int n)
{
        fct.clear();
        for (int i = 2; i * i <= n; ++i) if (n % i == 0) {
                fct.push_back(Pii(i, 0));
                while (n % i) ++fct.back().second, n /= i;
        }
        if (n > 1) fct.push_back(Pii(n, 1));
}

void dfs(int i, int gcd, int phi)
{
        if (i == fct.size()) {
                ret = (ret + (LL)pow_mod(k, gcd) * phi) % mod;
                return;
        }
        dfs(i + 1, gcd, phi);
        phi *= fct[i].first - 1;
        rep(j,fct[i].second) {
                gcd /= fct[i].first;
                dfs(i + 1, gcd, phi);
                phi *= fct[i].first;
        }
}

int main()
{
        int T, cas = 0;
        scanf("%d", &T);

        while (T--) {
                scanf("%d%d", &n, &k);
                decomp(n);
                ret = 0;
                dfs(0, n, 1);
                ret = (LL)ret * pow_mod(n, mod - 2) % mod;
                printf("Case #%d: %d\n", ++cas, ret);
        }

        return 0;
}

Problem D. Dilettante

题目大意

问用 1×1×1×2 的四维块在可以旋转的情况下填充 2×2×4×n 四维空间的方案数,答案取模 1000000007

算法思路

将最后一维当作时间考虑可以发现,在某一时刻,前三维构成 2×2×4 0/1 状态立方体
对于每次转移,要么将两个相邻的0置1,要么将状态取反后到达下一时刻
我们可以先预处理构成某个状态的方案数 f[S]
对于第一种转移, ST 的转移系数为 f[TS]
考虑相邻时刻的转移, ST 的转移系数为 f[TS] ,其中

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值