题意:按一定规则产生一个多项式,多项式的系数不难得知是C(n-1,i),求出哪些项的系数是m的倍数。n<=100000。
分析:理论上可根据C(n,k)=(n-k+1)/k*C(n,k-1)递推求出所有组合数,但太大无法存储。根据唯一分解原理,只要C(n-1,k)的质因数的指数>=m的质因数的指数即可,分解质因数也可由以上多项式递推。
#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<iomanip>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#define inf 10000000
#define pi acos(-1.0)
#define eps 1e-8
#define seed 131
using namespace std;
typedef pair<int,int> pii;
typedef unsigned long long ULL;
typedef long long LL;
const int maxn=100005;
int n,m;
int prime[maxn];
int o;
int e0[maxn];
int e[maxn];
int id[maxn];
map<int,int>pos;
int p;
void getPrime()
{
bool vis[maxn];
o=0;
memset(vis,0,sizeof(vis));
int m=sqrt(100000+0.5);
for(int i=2;i<=m;i++)
{
if(vis[i]==0)
{
for(int j=i*i;j<=100000;j+=i)
vis[j]=1;
}
}
for(int i=2;i<=100000;i++)
{
if(vis[i]==0)
{
pos[i]=o;
prime[o++]=i;
}
}
}
void addInteger(int c,int d)
{
int u=sqrt(c+0.5);
for(int i=0;i<o&&prime[i]<=u;i++)
{
if(c%prime[i]==0)
{
while(c%prime[i]==0)
{
e[i]+=d;
c/=prime[i];
}
}
if(c==1)
break;
}
if(c>1)
e[pos[c]]+=d;
}
bool F()
{
for(int i=0;i<p;i++)
{
if(!(e[id[i]]>=e0[id[i]]))
return false;
}
return true;
}
int main()
{
getPrime();
vector<int>vec;
while(~scanf("%d%d",&n,&m))
{
memset(e0,0,sizeof(e0));
memset(e,0,sizeof(e));
bool flag=true;
p=0;
for(int i=0;i<o;i++)
{
if(m%prime[i]==0)
{
while(m%prime[i]==0)
{
m/=prime[i];
e0[i]++;
}
id[p++]=i;
}
if(m==1)
break;
}
if(m>1)//m无法被100000以内的质数完全分解;
flag=false;
vec.clear();
for(int i=1;i<n-1;i++)
{
addInteger(n-1-i+1,1);//组合数一定能被100000以内的质数完全分解
addInteger(i,-1);
if(flag&&F())
vec.push_back(i+1);
}
int len=vec.size();
printf("%d\n",len);
for(int i=0;i<len;i++)
{
if(i==len-1)
printf("%d\n",vec[i]);
else
printf("%d ",vec[i]);
}
if(len==0)
printf("\n");
}
return 0;
}