CF 1312 Educational Codeforces Round 83 Div. 2 (A~C)

http://codeforces.com/contest/1312

A. Two Regular Polygons

http://codeforces.com/contest/1312/problem/A
题目大意:

对于正 n n n边形 A A A,是否存在正 m m m边形 B B B,满足:

  1. B B B的中心与 A A A的中心重合
  2. B B B的顶点都在 A A A的顶点上

第一行输入一个正整数 t t t ( 1 ≤ t ≤ 1 0 4 ) (1≤t≤10^4) (1t104),表示有 t t t 组输入,之后 t t t 行代表 t t t 组输入,每组输入一行两个空格分隔的正整数 n n n m m m ( 3 ≤ m < n ≤ 100 ) (3≤m<n≤100) (3m<n100),判断是否存在满足条件的多边形,存在输出"YES",否则输出"NO",一行一个输出。

结论:
n n n能被 m m m整除时,满足条件。
简单证明:
A A A的外接圆, A A A的每条边所对圆心角相等,设其大小为 α \alpha α。将 B B B的中心与 A A A的中心的重合,显然这个圆也是 B B B的外接圆,设B的每条边所对圆心角大小为 β \beta β。当 B B B的顶点在 A A A的顶点上时,显然有 β = k α \beta=k\alpha β=kα k k k为正整数)。又因为 n α = m β n\alpha=m\beta nα=mβ,所以 n = k m n=km n=km,即 n n n能被 m m m整除。
代码:

#include <cstdio>
using namespace std;
int main() {
    int t, m, n;
    while(~scanf("%d", &t)) {
        while(t--) {
            scanf("%d%d", &n, &m);
            printf(n % m ? "NO\n" : "YES\n");
        }
    }
    return 0;
}

B. Bogosort

http://codeforces.com/contest/1312/problem/B
题目大意:
给定数列 a 1 , a 2 , ⋯   , a n a_1,a_2,\cdots,a_n a1,a2,,an,对于任意的下标 i , j ( i < j ) i,j(i<j) i,j(i<j) 满足 j − a j ≠ i − a i j−a_j≠i−a_i jaj=iai ,则称这个数列是“好的”,现在给你一个数列 a a a,重新排列元素的顺序,将这个数列 a a a变成“好的”。

第一行输入一个正整数 t t t ( 1 ≤ t ≤ 100 ) (1≤t≤100) (1t100),表示有 t t t 组输入,之后 2 t 2t 2t 行代表 t t t 组输入,每组输入第一行一个正整数 n ( 1 ≤ n ≤ 100 ) n (1≤n≤100) n(1n100)表示数列 a a a 的长度,第二行输入 n n n 个正整数 a 1 , a 2 , ⋯   , a n ( 1 ≤ a i ≤ 100 ) a_1,a_2,\cdots,a_n(1≤ai≤100) a1,a2,,an(1ai100)

输出一行重新排序后的数列。

思路:
j − a j ≠ i − a i j−a_j≠i−a_i jaj=iai 改变一下形式,得到 i − j ≠ a i − a j i−j≠a_i-a_j ij=aiaj ,因为 i < j i<j i<j ,只要满足 a i − a j ≥ 0 a_i-a_j ≥ 0 aiaj0,即 a i ≥ a j a_i≥ a_j aiaj 不等式一定成立,所以将数组降序排列就一定是“好的”。
代码:

#include <bits/stdc++.h>
using namespace std;
int main() {
    int t, n, a[105];
    while(~scanf("%d", &t)) {
        while(t--) {
            scanf("%d", &n);
            for(register int i = 0; i < n; ++i)
                scanf("%d", a + i);
            sort(a, a + n, greater<int>());
            for(register int i = 0; i < n; ++i)
                printf(i == n - 1 ? "%d\n" : "%d ", *(a + i));
        }
    }
    return 0;
}

C. Adding Powers

http://codeforces.com/contest/1312/problem/C
题目大意:
对一初始各项均为 0 0 0 的数列 v 1 , v 2 , ⋯   , v n v_1,v_2,\cdots,v_n v1,v2,,vn,有如下算法:
在第 i i i i i i 0 0 0 开始)次操作,可以进行以下两种操作的其中一种:

  • 选择一个位置 p o s ( 1 ≤ p o s ≤ n ) pos (1≤pos≤n) pos(1posn),给 v p o s v_{pos} vpos 加上 k i k^i ki
  • 不选择任何位置并跳过这步。

你可以决定算法怎么进行以及何时停止,现给出一个数列 a a a ,能否在若干次操作后使 v v v 等于 a a a (即数列中每个元素对应相等)。

第一行输入一个正整数 T T T ( 1 ≤ T ≤ 1000 ) (1≤T≤1000) (1T1000),表示有 T T T 组输入,之后有 2 T 2T 2T 行,每 2 2 2 行为 1 1 1 组输入,每组输入第一行两个正整数 n n n k ( 1 ≤ n ≤ 30 , 2 ≤ k ≤ 100 ) k (1≤n≤30, 2≤k≤100) k(1n30,2k100) ,第二行 n n n 个正整数 a 1 , a 2 , ⋯   , a n ( 0 ≤ a i ≤ 1 0 16 ) a_1,a_2,\cdots,a_n (0≤ai≤10^{16}) a1,a2,,an(0ai1016)

一行一个输出,如果 v v v 经过变换后能够变为 a a a,输出"YES",否则输出"NO"。

思路:
要使 v v v 能够变为 a a a a a a 中的每一项一定是 k k k的若干次幂的和。

联想到进制转换中位权的概念。比如将 ( 3 A ) 16 (3A)_{16} (3A)16转化为十进制,进行的计算为 10 × 1 6 0 + 3 × 1 6 1 10\times16^0 + 3 \times16^1 10×160+3×161 得到十进制数 58 58 58。而对于题目中的操作, k k k i i i 次幂就相当于位权,因此将 a a a 中的数都转化为 k k k 进制。

由于 i i i 是不会重复的,开一个数组 c n t cnt cnt 记录各个指数出现的次数,大于 1 1 1 说明 v v v 无法变为 a a a。此外, k i k^i ki 前的系数为 1 1 1,所以 k k k 进制数中应当只含有 0 0 0 1 1 1,否则 v v v 也无法变为 a a a。注意 a a a 的范围, l o g 2 1 0 16 log_210^{16} log21016 约为 53.15 53.15 53.15,因此保险起见数组 c n t cnt cnt 开到60。

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

int t, n, k, cnt[60];
ll a[31];

inline bool judge(ll a[], int k) {
    for(register int i = 0; i < n; ++i) {
        for(register int j = 0; a[i]; ++j) {
            int r = a[i] % k;
            if(r == 1)
                ++cnt[j];
            else if(r > 1)
                return false;
            a[i] /= k;
        }
    }
    for(register int i = 0; i < 60; ++i) {
        if(cnt[i] > 1)
            return false;
    }
    return true;
}

int main() {
    while(~scanf("%d", &t)) {
        while(t--) {
            scanf("%d %d", &n, &k);
            for(register int i = 0; i < n; ++i)
                scanf("%lld", a + i);
            memset(cnt, 0, sizeof(cnt));
            printf(judge(a, k) ? "YES\n" : "NO\n");
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hibiki.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值