唯一分解定理应用+组合数学

题目:UVA 1635

题目大意:

  对于给定的n个数a1,a2,a3....an,一次求出相邻两个数之和,将得到一个新的数列。重复上述操作,最后结果将变成一个数。问这个数除以m的余数与那些数无关?例如n=3,m=2时,第一次求和结果a1+a2,a2+a3,在求和a1+2a2+a3,它除以2的余数和a2无关,1<=n<=10^5,2<=m<=10^9

分析:

C(k,n)=(n-k+1)/k*C(k-1,n),如果直接去求C(i-1,n-1)会爆long long 。那么就用唯一分解定理先将m分解了,然后在对C(i-1,n-1)分解了,看他们的素因子的指数是否合理,如果合理就是倍数关系。所谓合理就是C(i-1,n-1)的每一个素因子指数都要大于等于m的素因子指数
代码:

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<math.h>
using namespace std;
const int max_=1e5+5;
int pow_prime[max_][2];
int fen[max_];
int num[max_];
int tot;
void putm(int n)
{
    tot=0;
    for(int i=2;i*i<=n;i++)
    {
        if(n%i==0)
        {
            int s=0;
            while(n%i==0)
            {
                s++;
                n/=i;
            }
            pow_prime[tot][0]=s;
            pow_prime[tot++][1]=i;
        }
    }
    if(n>1)
    {
        pow_prime[tot][0]=1;
        pow_prime[tot++][1]=n;
    }
}
bool check(int n,int k)
{
    int x=n-k+1;
    int y=k;
    for(int i=0;i<tot;i++)
    {
        int p=pow_prime[i][1];
        int& q=fen[i];
        while(x%p==0)//fen数组会累加,相当于递推
        {
            q++;
            x/=p;
        }
        while(y%p==0)
        {
            q--;
            y/=p;
        }
    }
    for(int i=0;i<tot;i++)
    {
        if(fen[i]<pow_prime[i][0])
            return 0;
    }
    return 1;
}
int main()
{
    int n, m;
    while(~scanf("%d %d",&n,&m))
    {
        putm(m);
        int sum=0;
        memset(fen,0,sizeof(fen));
        for(int i=1;i<n;i++)
        {
            if(check(n-1,i))
            {
                num[sum++]=i+1;
            }
        }
        printf("%d\n",sum);
        for(int i=0;i<sum;i++)
        {
            if(i==0)
                printf("%d",num[i]);
            else
                printf(" %d",num[i]);
        }
        printf("\n");
    }
}
View Code

猜你喜欢

转载自www.cnblogs.com/linhaitai/p/10011772.html