Think:
1埃式筛法筛取素数
2唯一分解定理
3组合数公式(C(k, n) = ((n-k+1)/k)*C(k-1, n))
以下为Accepted代码
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
int is_primes[104000], pr, primes[104000], im, pm[24], em[24];///pm数组记录m分解之后的质因子,em数组记录m分解之后的质因子的指数
int n, m, tp, link[104000];
void Primes();///筛法筛取素数
void Primes_factor(int u);///唯一分解定理
bool Judge(int x, int y);///组合数递推公式(C(k, n) = ((n-k+1)/k)*C(k-1, n))
int main(){
Primes();
while(scanf("%d %d", &n, &m) != EOF){
Primes_factor(m);
int d = n - 1;
tp = 0;
for(int k = 1; k <= d; k++){
int x = d - k + 1;
int y = k;
if(Judge(x, y)){
link[tp++] = k+1;
}
}
printf("%d\n", tp);
for(int i = 0; i < tp; i++)
printf("%d%c", link[i], i == tp-1? '\n': ' ');
if(tp == 0) printf("\n");
}
return 0;
}
void Primes(){///埃氏筛法筛取素数
pr = 0;
memset(is_primes, 0, sizeof(is_primes));
is_primes[1] = 1, is_primes[2] = 0;
for(int i = 2; i <= 32000; i++){///题意可知唯一分解定理最大需要表示1e9,只需筛取sqrt(1e9)?
if(!is_primes[i]){
primes[pr++] = i;
for(int j = i*2; j <= 32000; j += i){
is_primes[j] = 1;
}
}
}
}
void Primes_factor(int u){///唯一分解定理
im = 0;
memset(em, 0, sizeof(em));
for(int i = 0; i < pr; i++){
if(u % primes[i] == 0){
pm[im] = primes[i];
while(u % primes[i] == 0){
u /= primes[i];
em[im]++;
}
im++;
}
}
if(u != 1){///分解之后u != 1,则u肯定为大于32000的一个素数,因此需要记录
pm[im] = u;
em[im]++;
im++;
}
}
/*bool Judge(int x, int y){
for(int i = 0; i < im; i++){
while(x%pm[i] == 0 && (x /= pm[i])){
em[i]--;
}
while(y%pm[i] == 0 && (y /= pm[i])){
em[i]++;
}
if(em[i] > 0)
return false;
}
return true;
}*/
bool Judge(int x,int y)
{
bool flag = true;
for(int i=0; i<im; ++i)
{
while((x%pm[i]==0)&&(x/=pm[i]))
em[i]--;///除式分子部分
while(y%pm[i]==0&&(y/=pm[i]))
em[i]++;///除式分母部分
if(em[i]>0)
flag = false;
/*为什么直接在em[i]上面做操作,难道不会影响后面的判断吗?
答:本题目用到的组合数递推公式(C(k, n) = ((n-k+1)/k)*C(k-1, n))中前一项的系数会对后一项产生影响,因此如果要判断第r项,则必须要预处理前r项
*/
}
return flag;
}