解方程

描述

已知多项式方程:

a0+a1x+a2x2+...+anxn=0

求这个方程在[1, m]内的整数解(n 和 m 均为正整数)。

格式

输入格式

输入共 n+2 行。

第一行包含 2 个整数 n、m,每两个整数之间用一个空格隔开。

接下来的 n+1 行每行包含一个整数,依次为 a0,a1,a2,...,an

输出格式

第一行输出方程在[1, m]内的整数解的个数。

接下来每行一个整数,按照从小到大的顺序依次输出方程在[1, m]内的一个整数解。

样例1

样例输入1[复制]

2 10
1
-2
1

样例输出1[复制]

1
1

样例2

样例输入2[复制]

2 10
2
-3
1

样例输出2[复制]

2
1
2

样例3

样例输入3[复制]

2 10
1
3
2

样例输出3[复制]

0

限制

对于 30%的数据,0 < n ≤ 2, |ai|

≤ 100, an

≠ 0, m ≤ 100;

对于 50%的数据,0 < n ≤ 100, |ai|

10100 an

≠ 0,m ≤ 100;

对于 70%的数据,0 < n ≤ 100, |ai|

1010000 an

≠ 0,m ≤ 10000;

对于 100%的数据,0 < n ≤ 100, |ai|

1010000 an ≠ 0,m ≤ 1000000。

老师讲了一种奇怪的孙子定理方法,没有听懂

然后看了hzwer的程序:

 因为系数很大,肯定得用高精度

但是可以

我们可以假设 f(x)%a=0 则x

f(x+a)也可以

所以就好啦

#include<iostream>
#include<cstdio>
using namespace std;
const int p[]={11261,19997,22877,21893,14843};
int n,m;
int a[1000010],used[1000010]; 
string s[10010];
int f(int x,int p)
{
	int sum=0;
	for(int i=n;i>=0;i--)
	{
		sum*=x;
		sum%=p;
		sum+=a[i];
		sum%=p;
	}
	return sum%p;
}
int calc(string s,int p)
{
	int num=0;
	int f=1;
	for(int i=0;i<s.length();i++)
	{
		if(s[i]=='-')
		{
			f=-1;
			continue;
		}
		num*=10;
		num%=p;
		num+=s[i]-'0';
		num%=p;
	}
	num*=f;
	return num%p;
}
void mod(int p)
{
	for(int i=0;i<=n;i++)
	{
		a[i]=calc(s[i],p);
	}
	for(int i=1;i<p;i++)
		if(f(i,p)%p!=0)
			for(int j=0;j*p+i<=m;j++)
			{	
				if(!used[j*p+i])used[0]--;
				used[j*p+i]=1;
			}
}
int main()
{
	cin>>n>>m;
	for(int i=0;i<=n;i++)
		cin>>s[i];		
	used[0]=m;
	for(int i=0;i<5;i++)
		mod(p[i]);
	printf("%d\n",used[0]);
	for(int i=1;i<=m;i++)
	{
		if(!used[i])
			printf("%d\n",i);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值