版权声明:蒟蒻原创博客,大佬转载也需附上链接: https://blog.csdn.net/weixin_43810158/article/details/88687637
题目描述;
对于给定的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
提示:
无。
思路分析:
此题的意思就是求杨辉三角上的第n行上的数,有哪些被m整除。
而想一想被m整除,那么m所有的因子,这个数就一定有。
所以我们就可以用质因数的唯一分解求出因子。
然后再枚举杨辉三角的数,当然在运用二项式定理与Legendre定理存储m的因子相同的个数。
最后再比较它们的大小,一旦m的该因子个数比此数大,就可以判定他不是无关的元素。
代码实现:
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
#define ll long long
ll n,m,w1[1000005],w2[1000005],p1[1000005],p2[1000005],tot1,num[1000005],tot2;
void sep(ll x)
{
for(ll i=2;i*i<=x;i++)
{
if(x%i==0)
{
tot1++;
p1[tot1]=i;
while(x%i==0)
{
x/=i;
w1[tot1]++;
}
}
}
if(x>1)
{
tot1++;
p1[tot1]=x;
w1[tot1]=1;
}
}
bool sep2(ll x,ll y)
{
for(ll i=1;i<=tot1&&((p1[i]<=x)||(p1[i]<=y));i++)
{
int t=p1[i];
while(x%t==0&&x)
{
x/=t;
w2[i]++;
}
while(y%t==0&&y)
{
y/=t;
w2[i]--;
}
}
for(int i=1;i<=tot1;i++)
if(w2[i]<w1[i])
return 0;
return 1;
}
int main()
{
scanf("%lld%lld",&n,&m);
sep(m);
for(int i=1;i<=n-2;i++)
{
if(sep2(n-i,i))
{
tot2++;
p2[tot2]=i+1;
}
}
if(tot2)
for(int i=1;i<=tot2;i++)
printf("%lld\n",p2[i]);
else
printf("0");
}