C++ 数论学习 质因数分解 —— 无关的元素

引言

数论大法好,人间真善美。。。


题目

题目描述

对于给定的n个数a1,a2,...,an,依次求出相邻两数之和,将得到一个新数列。重复上述操作,最后结果将变成一个数。问这个数除以m的余数与哪些数无关?

例如n=3,m=2时,第一次求和得到a1+a2,a2+a3,再次求和得到a1+2a2+a3,它除以2的余数和a2无关。

输入

第1行:2个整数n和m(1<=n<=10^5, 2 <=m<=10^9)

输出

按升序列出与m无关的元素的序号,每行1个。

若与全部元素无关,输出0

样例输入

Copy (如果复制到控制台无换行,可以先粘贴到文本编辑器,再复制)

5 3

样例输出

3

分析及思路

经过手推之后,可以发现其系数就是杨辉三角中第 n-1 行的元素个数,问题就变为杨辉三角中第 n-1 行能被 m 整除的序号数

而我们知道对于 C( n , k ) = C( n , k - 1 ) * ( n - k + 1 ) / k 

而且在杨辉三角中,第一个数和最后的数的系数都为 1,即 C( n , 0 ) = 1 

那么C( n , 1 ) = C( n , 0 ) * ( n - 1 + 1)  / 1

C( n , 2 ) = C( n , 1 ) * ( n - 2 + 1 ) / 2 

然后就递推出所有的系数,但是在计算系数时,不可能直接算出来在取模,就要用到质因数分解

首先是将模数分解,然后就是分解系数,而系数就可以通过 C( n , k ) = C( n , k - 1 ) * ( n - k + 1 ) / k  推出

就是说 C( n , k ) 的质因数要继承 C( n , k - 1 ) 的质因数,再加上 ( n - k + 1 ) / k 的质因数

最后通过质因数分解判定是否能被整除


代码

结合代码理解消化啦

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#define ll long long 
using namespace std;
 
int n , pm[777777] , cntm[777777] , cnt , cntn[777777];
ll m ;
 
bool mo( int a , int b )
{
    int x = a - b + 1 ;
    int y = b ;
    for(int i = 1 ; i <= cnt ; ++ i )
    {
        while( x % pm[i] == 0 ) {//对 (n-k+1) 进行质因数分解
            x /= pm[i] ;
            cntn[i] ++ ;
        }
        while( y % pm[i] == 0 ) {//对 k 进行质因数分解
            y /= pm[i] ;         // k 是除数,所以要减去它的质因数
            cntn[i] -- ;
        }
    }
    for(int i = 1 ; i <= cnt ; ++ i ) {
        if( cntn[i] < cntm[i] )//判定是否能被整除
            return 0;
    } 
    return 1 ;
}
 
int main()
{
    scanf("%d%lld", &n , &m );
    for(int i = 2 ; i * i <= m ; ++ i ) {
        if( m % i == 0 ) {
            cnt ++ ; 
            pm[cnt] = i ;
            while( m % i == 0 ) {
                m /= pm[cnt];
                cntm[cnt] ++ ;
            }
        }
    }
    if( m > 1 ) {
        cnt ++ ;
        pm[cnt] = m ;
        cntm[cnt] ++ ;
    }//对模数进行质因数分解

    bool flag = 0 ;
    for(int i = 2 ; i <= n -1 ; ++ i ) {
        if( mo( n - 1 , i - 1 ) ) {
            printf("%d\n", i );
            flag = 1 ;
        }
    }
    if( !flag )
        printf("%d", 0 );
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_44013342/article/details/88661031