Luogu P2312 解方程

题目描述

已知多项式方程:

a_0+a_1x+a_2x^2+\cdots+a_nx^n=0a0​+a1​x+a2​x2+⋯+an​xn=0

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

输入输出格式

输入格式:

 

共 n + 2n+2 行。

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

接下来的 n+1n+1 行每行包含一个整数,依次为 a_0,a_1,a_2\ldots a_na0​,a1​,a2​…an​ 。

 

输出格式:

 

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

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

 

输入输出样例

输入样例#1: 复制

2 10 
1
-2
1

输出样例#1: 复制

1
1

输入样例#2: 复制

2 10
2
-3
1

输出样例#2: 复制

2
1
2

输入样例#3: 复制

2 10 
1  
3  
2  
 

输出样例#3: 复制

0

说明

对于 30\%30% 的数据:0<n\le 2,|a_i|\le 100,a_n≠0,m<1000<n≤2,∣ai​∣≤100,an​≠0,m<100 。

对于 50\%50% 的数据:0<n\le 100,|a_i|\le 10^{100},a_n≠0,m<1000<n≤100,∣ai​∣≤10100,an​≠0,m<100 。

对于 70\%70% 的数据:0<n\le 100,|a_i|\le 10^{10000},a_n≠0,m<10^40<n≤100,∣ai​∣≤1010000,an​≠0,m<104 。

对于 100\%100% 的数据:0<n\le 100,|a_i|\le 10^{10000},a_n≠0,m<10^60<n≤100,∣ai​∣≤1010000,an​≠0,m<106 。

 

这么这么这么这么这么这么这么这么这么这么这么这么这么这么这么这么这么这么大的数

除了高精度只有hash了,但高精度显然超时

所以·只能hash,

又因为单hash被卡,不信可以去刷一下BZOJ上的

但是双hash是安全的,bzoj上只有ZERO个人通过了

如果你担心,也可以写多hash

不过看起来只有70分(不过noip够了不对吗?)

读入优化输出优化开起来,能用位运算尽量使用,

判断是否为0的时候可以使用秦九韵算法(不就是分治吗?)

a0+x*a1+x^2*a2+……+x^n*an

=a0+x*(a1+x*a2+……+x^n-1*an)

=……

这不就是分治吗

公式不用写了自己去推吧(不是博主懒,而是博主想给你们思考一下:))

#include<cstdio>
#define ll long long 
const int p1=1e9+7,p2=6662333;
using namespace std;

const int N=105,M=1e6+5;;
int n,m,num,ans[M];
ll a1[N],a2[N];

void write(int x)
{
	if(!(x/10)) 
	{
		putchar(x+48); return;
	}
	write(x/10),putchar(x%10+48); 
}

void read(int i)
{
	bool f=0;char ch=getchar();
	while(ch<'0'||ch>'9')
	{
		if(ch=='-') f=1;
		ch=getchar();	
	}
	while(ch>='0'&&ch<='9')
		a1[i]=((a1[i]<<1)+(a1[i]<<3)+ch-'0')%p1,
		a2[i]=((a2[i]<<1)+(a2[i]<<3)+ch-'0')%p2,
		ch=getchar();
	if(f) a1[i]=-a1[i],a2[i]=-a2[i];
}

inline bool pd(int x)
{
	ll ret=a1[n];
	for(int i=n-1;i>=0;i--)
		ret=(ret*x+a1[i])%p1;
	if(ret!=0) return 0;
	ret=a2[n];
	for(int i=n-1;i>=0;i--)
		ret=(ret*x+a2[i])%p2;
	return ret==0;
}
int main()
{
	scanf("%d%d",&n,&m);	
	for(int i=0;i<=n;i++) read(i);
	num=0;
	for(int i=1;i<=m;i++)
		if(pd(i)) ans[++num]=i; 
	write(num),puts("");
	for(int i=1;i<=num;i++)
		write(ans[i]),puts("");
	return 0;
} 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值