就是看c(n-1,i)中那些数可以被m整除。
直接乘再来除这样数太大了。用c(n,i)=n-i+1/i *c(n,i-1);递推。然后看m的唯一分解的质因数在c(n,i)中出现的次数。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <vector>
using namespace std;
const int maxn = 1000005;
int c[maxn];
int a[maxn][2];
vector<int> v;
int num=0;
int n,m;
void factor()
{
int k=(int) sqrt(m) + 1;
int temp=m,flag=0;
for(int i=2;i<=k;i++)
{
int flag=0;
if(temp%i==0)
{
flag=1;
a[num][0]=i;
}
while(temp%i==0)
{
a[num][1]++;
temp=temp/i;
}
if(flag) num++;
if(temp==1) break;
}
if(temp!=1)
{
a[num][0]=temp;
a[num++][1]=1;
}
return ;
}
bool check(int n,int i)
{
int x=n-i+1;
for(int j=0;j<num;j++)
{
int h=a[j][0];
while(x%h==0)
{
c[j]++;
x=x/h;
}
while(i%h==0)
{
c[j]--;
i=i/h;
}
}
for(int j=0;j<num;j++)
{
if(c[j]<a[j][1])
return false;
}
return true;
}
int main()
{
while(scanf("%d %d",&n,&m)!=EOF)
{
num=0;
v.clear();
memset(a,0,sizeof(a));
memset(c,0,sizeof(c));
n--;
factor();
for(int i=1;i<=n-1;i++)
{
if(check(n,i))
v.push_back(i+1);
}
printf("%d\n",v.size());
for(int i=0;i<v.size();i++)
{
if(i!=0) printf(" ");
printf("%d",v[i]);
}
printf("\n");
}
return 0;
}