题目描述
对于给定的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
样例输入
5 3
样例输出
3
题解
经过计算可以发现,在最后的表达式中,a1~an的系数就是杨辉三角第n行的数,而我们知道杨辉三角第n行第k个数就等于C(n-1,k-1)。因为C(n-1,0)和C(n-1,n-1)同杨辉三角每一行首尾两个数一样是1,所以不用管它们。那么就需要找C(n-1,1)~C(n-1,n-2)中可以被m整除的数。(以下的n和k都没有-1,但是影响不大,代码中算n-1、k-1就行)
由公式 可知
,
所以 ,而C(n,0)等于1,然后就可以递推了。但是推出来的数太大,计算又不方便,所以把它表示为整数的唯一分解形式。设
…,x是m的质因数,a是每个质因数的指数。
把每个C(n,k)都表示成这种质因数分解的形式,那么如果C(n,k)的的指数小于m的,而x又都是质数,所以C(n,k)的分解中就没有其他任何数可以把m多出来的
约掉了,所以此C(n,k)就不能被m整除。
因为 ,所以C(n,k)的分解就是在前一个数C(n,k-1)的分解中,加上n-k+1的分解的各个质因数的指数,减去k的分解的各个质因数的指数。(有数学基础的人应该听得懂)
详见代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,i,j,num[50000],cnt1[50000],cnt2[50000],ans[50000],len,l;
long long m;
inline void fenjie(){
for(long long i=2;i<=m;i++){
if(m%i==0){
num[++len]=i;
while(m%i==0)m/=i,cnt1[len]++;
}
}
if(m>1)num[++len]=m,cnt1[len]=1;
}
inline bool ac(int n,int k){//C(n,k)=(n-k+1)/k*C(n,k-1)
int x=n-k+1,y=k;
for(int i=1;i<=len&&(num[i]<=x||num[i]<=y);i++){
while(x%num[i]==0&&x){
x/=num[i],cnt2[i]++;
}
while(y%num[i]==0&&y){
y/=num[i],cnt2[i]--;
}
}
for(int i=1;i<=len;i++)
if(cnt1[i]>cnt2[i])return 0;
return 1;
}
int main()
{
scanf("%d%lld",&n,&m);
fenjie();
for(i=1;i<n-1;i++)
if(ac(n-1,i))
ans[++l]=i+1;
if(l==0)puts("0");
else
for(i=1;i<=l;i++)
printf("%d\n",ans[i]);
return 0;
}