这个题 需要优化。 否则会超时。 C(m,n) 只能算一半。 另一半 用 减法 直接减掉。
刘汝佳P321 的书上写的公式要看懂。
意思就是 要使系数 能整出 m 那么 这个系数的 唯一分解式的 指数 要 大于等于 m的 唯一分解式的 指数
举个例子。 如果 二项式的 系数为 6 那么唯一分解式 2 的指数为 1 3的指数为1 m 如果为12 2 的指数为 2 3的指数为1 m的 2,3的指数 都大于6 的指数
所以一定可以整除。 还有一个问题。 如果 m很大的话 就输出0. 注意后面 多个空行 因为有0个元素 什么都不输出 一个空行。
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <string>
#include <map>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <cctype>
using namespace std;
#define ll long long
typedef unsigned long long ull;
#define maxn 100000+100
#define INF 1<<30
map <int, int> vis;
int s[maxn];
int m,n;
vector <int> q;
int res_m(){
int x = m;
for(int i = 2; i <= sqrt(x); i++){
if(m == 1)
break;
if(m % i == 0){
int tot = 0;
while(m % i == 0){
m /= i;
tot++;
}
vis[i] = tot;
q.push_back(i);
}
}
if(m > 1){
if(!vis.count(m)){
q.push_back(m);
vis[m] = 1;
}
else
vis[m] = 1;
}
}
int res(int k,int pan){
int x = k;
for(int j = 2; j <= sqrt(x); j++){
if(k == 1)
break;
if(k % j == 0){
int tot = 0;
while(k % j == 0){
k /= j;
tot++;
}
s[j] += tot*pan;
}
}
if(k > 1)
s[k] += pan;
}
int main (){
while(scanf("%d%d",&n,&m) != EOF){
n --;
memset(s,0,sizeof(s));
q.clear();
vis.clear();
vector <int> path;
res_m();
if(q[q.size() - 1] >= 100000) {
printf("0\n\n");
continue;
}
res(n,1);
int flag = 1;
int len = q.size();
for(int j = 0; j < len; j++){
if(vis[q[j]] > s[q[j]]){
flag = 0;
break;
}
}
set <int> biao;
if(flag){
path.push_back(2);
biao.insert(2);
if(!biao.count(n))
path.push_back(n);
}
for(int i = 2; i <= n/2; i++){
res(i,-1);
res(n - i + 1,1);
int flag = 1;
for(int j = 0; j < len; j++){
if(vis[q[j]] > s[q[j]]){
flag = 0;
break;
}
}
if(flag){
path.push_back(i+1);
biao.insert(i+1);
if(!biao.count(n-i+1))
path.push_back(n-i+1);
}
}
sort(path.begin(),path.end());
int len1 = path.size();
printf("%d\n",len1);
for(int i = 0; i < len1; i++){
if(i == 0) printf("%d",path[i]);
else printf(" %d",path[i]);
}
printf("\n");
}
return 0;
}