uva 1635(组合数+唯一分解定理)

同对m和n的每一项用唯一分解定理,比较次数,比m大则m是i的约数,否则不是,是约数,则无关

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <vector>
using namespace std;
const int maxn=100000+100;
int num[maxn][3];
int vis[maxn];
int c[maxn];
int cnt;
int n,m;
void init()
{
    memset(num,0,sizeof(num));
    memset(vis,0,sizeof(vis));
    memset(c,0,sizeof(c));
}
void factor()//m的唯一分解定理
{
    cnt=0;
    for(int i=2;i*i<=m;i++)
    {
        if(m%i==0)
        {
            cnt++;
            num[cnt][0]=i;
            while(m%i==0)
            {
                num[cnt][1]++;
                m=m/i;
            }
        }
    }
    if(m>1)
    {
        cnt++;
        num[cnt][0]=m;
        num[cnt][1]=1;
    }
}
bool check(int i,int n)//前一项已经对C进行过计算,所以只算者这一项的就可以
{
    int y=(n-1)-i+1;
    int x=i;
    for(int j=1;j<=cnt;j++)
    {
        while(y%num[j][0]==0)
        {
            c[j]++;
            y=y/num[j][0];
        }

        while(x%num[j][0]==0)
        {
            c[j]--;
            x=x/num[j][0];

        }
    }
    for(int j=1;j<=cnt;j++)//次数必须大于m的同质数项的次数
      if(c[j]<num[j][1]) return 0;
    return 1;
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        init();
        factor();
        int ans=0;
        for(int i=1;i<n-1;i++)//注意有n项,但是组合数计算时时C(0,n-1),C(1,n-1)......C(n-1,n-1);
        {
            if(check(i,n))
            {
                ans++;
                vis[i]=1;
            }
        }
        printf("%d\n",ans);
        int first=0;
        for(int i=1;i<n-1;i++)
        if(vis[i])
        {
            if(!first) first=1;
            else printf(" ");
            printf("%d",i+1);
        }
        printf("\n");
    }
    return 0;
}

 

posted on 2018-02-03 10:57  发牌员  阅读(111)  评论(0)    收藏  举报

导航