NOIP提高组2014解方程 解题报告

题目链接

LGOJ P2312 解方程

解题思路

确定性做法?很抱歉,我不会。
下面讲试根法。
一条很显然的结论
设函数 f ( x ) = a 0 + a 1 x + a 2 x 2 + . . . + a n x n f(x)=a_0+a_1x+a_2x^2+...+a_nx^n f(x)=a0+a1x+a2x2+...+anxn
则原方程化为 f ( x ) = 0 f(x)=0 f(x)=0
故我们只要找到函数 f ( x ) f(x) f(x)的零点即可。可以采用试根法。我们枚举题目给定的范围 [ 1 , m ] [1,m] [1,m]中的每个整数 x x x,判断它是不是函数零点,即判断 f ( x ) f(x) f(x)是否 = = 0 ==0 ==0
嗯,这样对于50%的数据应该能过。期望得分:50pts

然而,对于100%的数据,我们发现 ∣ a ∣ |a| a过大,大得离谱。我们怎么做呢?
我们来讲讲一种HASH做法
我们要求 x x x,使满足 f ( x ) = a 0 + a 1 x + a 2 x 2 + . . . + a n x n = 0     ( ∗ ) f(x)=a_0+a_1x+a_2x^2+...+a_nx^n=0\ \ \ (*) f(x)=a0+a1x+a2x2+...+anxn=0   ()成立。如果我们的 x x x满足 f ( x ) = a 0 + a 1 x + a 2 x 2 + . . . + a n x n ≡ 0 ( m o d   P ) f(x)=a_0+a_1x+a_2x^2+...+a_nx^n\equiv0(mod\ P) f(x)=a0+a1x+a2x2+...+anxn0(mod P)且P是一个大质数的话,这个 x x x有很大的概率满足 ( ∗ ) (*) ()式。(嗯,就是这么玄学)
好的,我们只要预先对每个 a i a_i ai进行 m o d   P mod\ P mod P操作即可。(据某机房大佬说,在 m o d   P mod\ P mod P意义下的 + 、 − 、 ∗ +、-、* +操作可以乱搞)

那么有同学就要问了,这个概率就很玄学了啊2333。没有关系,就像Miller-Rabin算法一样,我们可以多选几个质数,可以进一步降低错误率。
(本解题报告代码就使用了两个,您可以多加几个嘛)

详细代码

#define USEFASTERREAD 1 

#define rg register
#define inl inline
#define DEBUG printf("[Passing [%s] in line %d.]\n", __func__, __LINE__)
#define putline putchar('\n')
#define putsp putchar(' ')
#define Rep(a, s, t) for(rg int a = s; a <= t; a++)
#define Repdown(a, t, s) for(rg int a = t; a >= s; a--)
typedef long long ll;
#include<cstdio>
#define rs freopen("test.in", "r", stdin), freopen("test.out", "w", stdout)

#if USEFASTERREAD
char In[1 << 20], *ss = In, *tt = In;
#define getchar() (ss == tt && (tt = (ss = In) + fread(In, 1, 1 << 20, stdin), ss == tt) ? EOF : *ss++)
#endif
struct IO
{
	void RS() {rs;} 
	template<typename T> inline IO r(T& x)const
	{
	    x = 0; T f = 1; char ch = getchar();
	    for(; ch < '0' || ch > '9'; ch = getchar()) if(ch == '-') f = -1;
	    for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + int(ch - '0');
	    x *= f; return *this;
	}
	template<typename T> inline IO w(T x)const
	{
	    if(x < 0) {putchar('-'); x = -x;}
	    if(x >= 10) w(x / 10);
	    putchar(x % 10 + '0'); return *this;
	}
	template<typename T> inline IO wl(const T& x)const {w(x), putline; return *this;}
	template<typename T> inline IO ws(const T& x)const {w(x), putsp; return *this;}
	inline IO l() {putline; return *this;}
	inline IO s() {putline; return *this;}
}io;
template<typename T> inline T Max(const T& x, const T& y) {return y < x ? x : y;}
template<typename T> inline T Min(const T& x, const T& y) {return y < x ? y : x;}
template<typename T> inline void Swap(T& x, T& y) {T tmp = x; x = y; y = tmp;}
#include<vector>
using namespace std;
typedef pair<int, int> pii;
const int MO1 = 1000000007;
const int MO2 = 998244353;
pii read()
{
	int x1 = 0, x2 = 0; int f = 1; char ch = getchar();
	for(; ch < '0' || ch > '9'; ch = getchar()) if(ch == '-') f = -1;
	for(; ch >= '0' && ch <= '9'; ch = getchar())
		x1 = (1ll * x1 * 10 + int(ch - '0')) % MO1,
		x2 = (1ll * x2 * 10 + int(ch - '0')) % MO2;
	x1 *= f, x2 *= f; return pii(x1, x2);
}
int a1[105];
int a2[105];
int n, m;
bool f1(int x)
{
	int ans = 0;
	for(rg int i = n; i >= 0; i--)
		ans = ((1ll * ans * x) % MO1 + a1[i]) % MO1;
	return ans == 0;
}
bool f2(int x)
{
	int ans = 0;
	for(rg int i = n; i >= 0; i--)
		ans = ((1ll * ans * x) % MO2 + a2[i]) % MO2;
	return ans == 0;
}
int ans;
vector<int> vans;
int main()
{
    //io.RS();
    io.r(n).r(m);
    for(rg int i = 0; i <= n; i++)
    {
		pii t = read();
		a1[i] = t.first;
		a2[i] = t.second;
	}
	for(rg int i = 1; i <= m; i++)
		if(f1(i) && f2(i))
		{
			ans++;
			vans.push_back(i);
		}
	io.wl(ans);
	for(rg int i = 0; i < vans.size(); i++)
		io.wl(vans[i]);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

日居月诸Rijuyuezhu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值