阶乘和的关系
题目链接
题目大意:
给定n个正整数和一个数k,问这n个数的阶乘之和能不能被k的阶乘整除,既:(a[1]!+a[2]!+a[3]!+....+a[n]!) % k! == 0。
题目分析:
对于一个连续的阶乘我们可以对其进行合并。如:
3*2!+ 3*3! = 3!+3*3! = 4*3! = 4!
那么我们可以进行低位阶乘转化为高位阶乘,即
for (int i = 1; i <= n; i++) {
// while (a[i] > i) { //也可以这样写
// a[i + 1] ++;
// a[i] = a[i] - (i + 1);
// }
//将阶乘高阶化
a[i + 1] += a[i] / (i + 1);
a[i] %= (i + 1);
}
根据数学加法关系,如果每一个加数都可以被x整除的话,那他们的和也一定可以被x整除,相反则不能被x整除(我也不知道怎么证明0^0)。那么我们就可以用一个长度为5e5+10是数组(或者桶)来存储阶乘数,对其进行阶乘升高化,然后在判断1——x-1出是否有数存在(即是否有不是x!的倍数的加法因子)。如果有就输出No,否则输出Yes。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 5e5 + 10;
int a[N]; //存放阶乘个数
signed main() {
int n, x;
cin >> n >> x;
for (int i = 1; i <= n; i ++) {
int x;
cin >> x;
a[x] ++;
}
for (int i = 1; i <= n; i++) {
// while (a[i] > i) { //也可以这样写
// a[i + 1] ++;
// a[i] = a[i] - (i + 1);
// }
//将阶乘高阶化
a[i + 1] += a[i] / (i + 1);
a[i] %= (i + 1);
}
bool p = true; //根据加法法则,如果每一个加数都可以被x整除,那么他们的和也一定能被X整除
for (int i = 1; i < x; i++) {
if (a[i]) {
p = false; //存在未被整除的,其结果不能被整除
break;
}
}
if (p) puts("Yes");
else puts("No");
return 0;
}
没有什么能阻止我对知识的追求!!!