例10-6 uva1635(唯一分解定理)

题意:给定n个数a1,a2····an,依次求出相邻两个数值和,将得到一个新数列,重复上述操作,最后结果将变为一个数,问这个数除以m的余数与那些数无关?


思路:最后观察期规律符合杨辉三角,那么,问题就可以变成判断C(0,n-1),C(1,n-1)。。。。C(n-1,n-1)哪些是m的倍数,所以只需考虑m唯一分解后在C(i,n-1)中的情况

公式:C(k,n)=(n-i+1)*c(i-1,n)/k. 然后利用递推公式检查m的因子,只要(n-i+1)/i是m倍数即可


#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <map>
#include <vector>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;

int pm[1000],nm[1000];
int cur;


void ini(int m)       //分解m
{
    cur = 0;
    memset(pm,0,sizeof(pm));
    memset(nm,0,sizeof(nm));
    for(int i = 2; i*i <= m ; i ++)
    {
        if(m % i == 0)
        {
            pm[cur] = i;
            while(m % i == 0)
            {
                m /= i;
                nm[cur]++;
            }
            cur++;
        }
    }
    if(m > 1)
    {
        pm[cur] = m;
        nm[cur++] = 1;
    }
}

bool can_do(int x,int y)       //检查因子
{
    bool flag=true;
    for(int i=0; i<cur; ++i)
    {
        while((x%pm[i]==0) && (x/=pm[i]))
            nm[i]--;
        while((y%pm[i]==0) && (y/=pm[i]))
            nm[i]++;
        if(nm[i]>0)
            flag=false;
    }
    return flag;
}
int ans[100050];

int main()
{
    int m,n;
    while(~scanf("%d%d",&n,&m))
    {
        ini(m);
        int tot = 0;
        for(int i = 1; i <= n; i++)
        {
            if(can_do(n-i,i))   //n-i  =  (n-1)-i+1
            {
                ans[tot++] = i+1;
            }
        }
        printf("%d\n",tot);
        if(tot !=  0)
        {
            for(int i = 0; i < tot-1; i++)
                if(ans[i])
                    printf("%d ",ans[i]);
            printf("%d",ans[tot-1]);

        }
        printf("\n");
    }
    return 0;
}

  

posted @ 2015-10-10 18:46  Przz  阅读(177)  评论(0编辑  收藏  举报