【hash】BZOJ3751-[NOIP2014]解方程

【题目大意】

已知多项式方程:a0+a1*x+a2*x^2+...+an*x^n=0。求这个方程在[1,m]内的整数解(n和m均为正整数)。

【思路】

*当年考场上怒打300+行高精度,然而没骗到多少orz 然而正解只有60+行

[前铺]f(n) mod p=f(n mod p) mod p

取四个素数,分别对每个ai取模。先预处理x=0..p-1的情况,直接代入多项式计算即可。再在O(m)时间内检验1..m,对于≥p的利用前铺公式可得。如果模四个素数结果均能得到0,说明这个数是方程的解。

P.S.这个的前提是你的脸好……我一开始随便取的四个就WA了QAQ

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int MAXN=100+5;
 4 const int MAXM=1000000+5;
 5 const int MAXP=30000;
 6 typedef long long ll;
 7 int prime[4]={17389,22349,22367,22369};
 8 int n,m,a[MAXN],hash[MAXN][4],table[MAXP][4],ans[MAXM],cnt=0;
 9
10 ll get_table(int j,int x)
11 {
12     ll ret=0;
13     for (int i=n;i>=0;i--)
14         ret=(ret*x+hash[i][j])%prime[j];
15     return ret;
16 }
17
18 int read(int x)
19 {
20     char str[10010];
21     scanf("%s",str);
22     int negative=0;
23     for (int i=0;str[i];i++)
24     {
25         if (str[i]==‘-‘) negative=1;
26             else for (int j=0;j<4;j++)
27                     hash[x][j]=((hash[x][j]*10)%prime[j]+(str[i]-‘0‘))%prime[j];
28     }
29     if (negative)
30         for (int j=0;j<4;j++)
31             hash[x][j]=(prime[j]-hash[x][j])%prime[j];
32 }
33
34 void init()
35 {
36     memset(hash,0,sizeof(hash));
37     scanf("%d%d",&n,&m);
38     for (int i=0;i<=n;i++) read(i);
39     for (int i=0;i<4;i++)
40         for (int j=0;j<prime[i];j++) table[j][i]=get_table(i,j);
41 }
42
43 void solve()
44 {
45     for (int i=1;i<=m;i++)
46     {
47         int flag=1;
48         for (int j=0;j<4;j++)
49             if (table[i%prime[j]][j])
50             {
51                 flag=0;
52                 break;
53             }
54         if (flag) ans[++cnt]=i;
55     }
56     printf("%d\n",cnt);
57     for (int i=1;i<=cnt;i++) printf("%d\n",ans[i]);
58 }
59
60 int main()
61 {
62     init();
63     solve();
64     return 0;
65 } 
时间: 2024-08-07 08:39:20

【hash】BZOJ3751-[NOIP2014]解方程的相关文章

BZOJ3751 NOIP2014 解方程(Hash)

题目链接  BZOJ3751 这道题的关键就是选取取模的质数. 我选了4个大概几万的质数,这样刚好不会T 然后统计答案的时候如果对于当前质数,产生了一个解. 那么对于那些对这个质数取模结果为这个数的数也要统计进答案. #include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b); ++i) #define dec(i, a, b) for (int i(a); i &g

bzoj3751: [NOIP2014]解方程 数学

题解:http://www.cnblogs.com/mhy12345/p/4109764.html 我也不知道该怎么选质数才比较优越,但是可以用秦九韶算法优化常数,就容易过了. #include<bits/stdc++.h> using namespace std; int f[5]={ 16253,21139,22433,23059,27647 }; int a[5][101]; bool v[5][100000]; char t[10057]; int cnt,st[1000001]; b

【秦九韶算法】【字符串哈希】bzoj3751 [NOIP2014]解方程

在模意义下枚举m进行验证,多设置几个模数,而且小一些,利用f(x+p)%p=f(x)%p降低计算次数.UOJ AC,bzoj OLE. #include<cstdio> #include<iostream> #include<cstring> #include<vector> using namespace std; #define MAXV 4951 vector<int>v; typedef unsigned int ull; const u

BZOJ3751: [NOIP2014]解方程

既然bzoj上有这道题了就把这个坑填了吧... 题解见:http://blog.csdn.net/popoqqq/article/details/40984859 话说这个解法如果当时想到冲突的概率很小的话应该就能想出来233 代码: 1 #include<cstdio> 2 3 #include<cstdlib> 4 5 #include<cmath> 6 7 #include<cstring> 8 9 #include<algorithm>

【BZOJ 3751】 [NOIP2014]解方程

3751: [NOIP2014]解方程 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 914  Solved: 173 [Submit][Status][Discuss] Description 已知多项式方程: a0+a1*x+a2*x^2+...+an*x^n=0 求这个方程在[1,m]内的整数解(n和m均为正整数). Input 第一行包含2个整数n.m,每两个整数之间用一个空格隔开. 接下来的n+1行每行包含一个整数,依次为a0,a1,

【bzoj3751】[NOIP2014]解方程 数论

题目描述 已知多项式方程: a0+a1*x+a2*x^2+...+an*x^n=0 求这个方程在[1,m]内的整数解(n和m均为正整数). 输入 第一行包含2个整数n.m,每两个整数之间用一个空格隔开. 接下来的n+1行每行包含一个整数,依次为a0,a1,a2,...,an. 输出 第一行输出方程在[1,m]内的整数解的个数. 接下来每行一个整数,按照从小到大的顺序依次输出方程在[1,m]内的一个整数解. 样例输入 2 10 2 -3 1 样例输出 2 1 2 题解 真心不难的数论题 首先高精度

[noip2014]解方程 hash+秦九昭

坑啊= = 选了好几次质数,发现还是这一组靠谱 思路:每次mod之后求出所有解,再mod再求,看着复杂度差不多了就把没重复的都输出就行了 const mi:array[1..7] of int64=(12537,15437,17647,14677,10003,10009,10007); var n,m,shi,sum,x:int64; i,j,k,y1:longint; a:array[-1..102,-1..10000+9] of int64; flag:array[-1..1000000+9

noip2014 解方程(本博文转载于http://blog.csdn.net/popoqqq/article/details/40984859,略有删减)

首先阿贝尔在200年前告诉我们 五次以上方程没有求根公式 于是我们只能枚举1~m 这个是100W 然后100W再加上1W位的精度 都不用运算直接就是跪…… 怎么办呢QAQ 哈希大法好! 令f(x)=an*x^n+...+a1*x^1+a0*x^0 易知若f(x)=0 则f(x) mod p=0 反之如果f(x) mod p=0 那么我们基本可以得出f(x)=0 p比较靠谱的时候碰撞率极低 所以我们把所有的ai都对p取模 然后对于每个解O(n)验证即可 这样是O(m*n)=10 8 (不是一秒么

NOIP2014解方程

题目:求一个n次整系数方程在1-m内的整数解  n<=100 系数<=10000位 m<=100W 题解:最暴力的想法是枚举x,带入求值看是否为0. 这样涉及到高精度乘高精度,高精度乘单精度,高精度加高精度和高精度减高精度. 复杂度 n*m*len*len ,显然只能过30%的数据 让我们考虑优化: 我们先来研究一下这个算法的主要耗时在哪里 1)将x带入方程左边求值 2)选择多少x带入 我们考虑第一个优化 1)秦九韶算法 只要我们把原方程左边化为 ((An*x+An-1)*x+An-2)