1. 程式人生 > >唯一分解定理應用+組合數學

唯一分解定理應用+組合數學

題目: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