长安大学第四届ACM-ICPC“迎新杯”程序设计竞赛-重现赛 D - 新卡片游戏

题目描述

𝑐𝑡𝑟与𝑑𝑓𝑑在玩一个游戏,𝑐𝑡𝑟有𝑛张卡片,每张卡片上写了一个数字,其中第𝑖张卡片上的数字为𝑎𝑖。𝑑𝑓𝑑说出了一个质数𝑝,并指出可以将𝑛张卡片重新排列使得相邻两张卡片上数字的乘积是𝑝2 的倍数,即重新排列后满足𝑎𝑖 × 𝑎𝑖+1 𝑚𝑜𝑑 𝑝2 = 0(𝑖 < 𝑛)。𝑐𝑡𝑟 对此表示怀疑,并与𝑑𝑓𝑑打赌,输的人会受到相应的惩罚。
𝑑𝑓𝑑欣然接受了他的挑战,他想知道自己能否赢得这次赌注。

输入描述:

输入第一行为一个整数𝑇(1 ≤ 𝑇 ≤ 20),表示一共有𝑇组测试数据。
对于每组测试数据:
第一行有两个整数𝑛(2 ≤ 𝑛 ≤ 104)和𝑝(1 ≤ 𝑝 ≤ 105),表示卡片总数与𝑑𝑓𝑑提到的的质数。
第二行有𝑛个整数,其中第𝑖个数字𝑎𝑖(1 ≤ 𝑎𝑖 ≤ 105)代表了第𝑖张卡片上的字母。
数据保证𝑝是一个质数。

输出描述:

对于每组测试数据,输出如果dfd能够赢得这次赌注输出“YES”,否则输出“NO”。
示例1

输入

2
5 2
4 4 1 1 1
5 3
3 3 2 2 2

输出

YES
NO

说明

对于第一组样例,卡片重新排列成1 4 1 4 1便能够满足要求。
对于第二组样例,不论怎么排序都无法满足要求。

题解

分析。

先处理出每个数能被几个$p$除掉,然后只要考虑$0$的个数和大于等于$2$的个数就可以了。

因为只有大于等于$2$的东西才可以消掉$0$。

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

const int maxn = 10000 + 10;
int T, n, p;

int main() {
  scanf("%d", &T);
  while(T --) {
    scanf("%d%d", &n, &p);
    int sum0 = 0, sum2 = 0;
    for(int i = 1; i <= n; i ++) {
      int x;
      scanf("%d", &x);
      int k = 0;
      while(x) {
        if(x % p) break;
        k ++;
        x = x / p;
      }
      if(k == 0) sum0 ++;
      if(k >= 2) sum2 ++;
    }
    if(sum2) {
      sum0 = sum0 - min(sum0, sum2 + 1);
    }
    if(sum0 == 0) printf("YES\n");
    else printf("NO\n");
  }
  return 0;
}

  

posted @ 2017-12-21 15:15  Fighting_Heart  阅读(388)  评论(0编辑  收藏  举报