UVa 1635 查找无关项(组合数+唯一分解定理)

题目链接
题目大意:给定整数n、m,对于给定的n个数a1、a2、a3、……、an,依次求出相邻两项之和,重复直至只存在一个数,判断最终多项式除以m的余数与那些数无关?

输入
3 2  //m,n
输出
1  //最终无关项个数
2  //逐个输出无关项下标,升序输出

解释:
a1 --------- a2 -------- a3
----a1+a2 ----- a2+a3
--------a1+2a2+a3
最终得到多项式 a1+2a2+a3
,此时m=2,无关项为a2。
再列列n=5的情况,易发现其规律。

思路:
每个系数均可写成组合数形式,且正好是杨辉三角第n-1行各数,易想到枚举每一个系数C(n,k)(k为第k项),判断其能不能被m整除,若可及是无关项,但考虑到n很大,这种想法是行不通的。

可整除又可等价于被除数能够整除除数的每个因子,而又根据唯一分解定理可将m先行分解,在根据公式在这里插入图片描述依次计算各个素因子在系数中的次数,每次从左到右计算系数的时候,只需要考虑(n-k+1)/k,因为在上一次已经计算过了,它的素因子次数已经保存下来了。
再根据公式UVa 1635 查找无关项(组合数+唯一分解定理)_第1张图片可简化一半的判断次数,运用优先队列进行一定优化。

交题时一直Presentation error,被输出搞了,注意:末尾无空格,然后即便无无关项也要空行。

#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAXN = 1e6 + 7;
typedef long long ll;
const ll HEIGH = 1e18 + 7;
int n, m, num;
int fac[105][2];  //f[][0]用来存储质因子,f[][1]存储对应质因子的个数
int cnt[105]; //记录每个质因数在分母分子出现的次数
priority_queue <int, vector<int>, greater<int> > q;//记录最终无关项
void factor(){//分解质因子
	for (int i = 2; i*i <= m; i++){
		if (m%i == 0){
			fac[++num][0] = i;
			fac[num][1] = 0;
			while (m%i == 0){
				fac[num][1]++;
				m /= i;
			}
		}
	}
	if (m>1){//剩余数 
		fac[++num][0] = m;
		fac[num][1] = 1;
	}
}
bool check(int k){
	int zi = n - k + 1, mu = k;
	for (int i = 1; i <= num; i++){
		int mod = fac[i][0];
		while (zi%mod == 0){
			cnt[i]++;
			zi /= mod;
		}
		while (mu%mod == 0){
			cnt[i]--;
			mu /= mod;
		}
	}
	for (int i = 1; i <= num; i++){
		if (cnt[i] < fac[i][1])
			return false;
	}
	return true;
}
int main(){
	while (scanf("%d %d", &n, &m) != EOF){
		memset(cnt, 0, sizeof(cnt));
		memset(fac, 0, sizeof(fac));
		num = 0;
		n--;
		factor();
		for (int i = 1; i <= n / 2 ; i++){
			if (check(i)){
				q.push(i + 1);
				if (i + 1 != n - i + 1)
					q.push(n - i + 1);
			}
		}
		int length = q.size();
		printf("%d\n", length);
		bool flag = true;
		while (!q.empty()){
			if (flag){
				printf("%d", q.top());
				flag = false;
			}
			else printf(" %d", q.top());
			q.pop();
		}
		printf("\n");
	}
	return 0;
}

你可能感兴趣的:(acm,算法)