BZOJ 3751 [NOIP2014]解方程

题解:运用筛法的思想,%p意义下,F(x)!=0则F(x+p)!=0

多选几个质数把F(x)!=0的筛去就可以了

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

int n,m;
int ans;
int vis[1000009];

int p[51]={0,30011,11261,14843,19997,21893};
int a[200][51];

void Minit(){
	memset(a,0,sizeof(a));
	memset(vis,0,sizeof(vis));
	ans=0;
}

char s[100009];
int main(){
	scanf("%d%d",&n,&m);
//	for(int i=1;i<=50;++i)p[i]=10000+i;
	Minit();
	for(int i=0;i<=n;++i){
		scanf("%s",s);
		int len=strlen(s);
		for(int k=1;k<=5;++k){
			if(s[0]!=‘-‘){
				a[i][k]=s[0]-‘0‘;
			}else{
				a[i][k]=0;
			}
			for(int j=1;j<len;++j){
				a[i][k]=(a[i][k]*10+(s[j]-‘0‘))%p[k];
			}
			if(s[0]==‘-‘){
				a[i][k]=(-a[i][k]+p[k])%p[k];
			}
		}
	}
//	for(int i=0;i<=n;++i)cout<<a[i][1]<<‘ ‘;
//	cout<<endl;
	for(int k=1;k<=5;++k){
		for(int j=1;j<=min(p[k],m);++j){
			long long fx=0;
			for(int i=n;i>=0;--i)fx=(fx*j+a[i][k]+p[k])%p[k];
//			cout<<fx<<endl;
			if(fx){
				for(int d=0;j+p[k]*d<=m;++d)vis[j+p[k]*d]=1;
			}
		}
	}

	for(int i=1;i<=m;++i)if(!vis[i])++ans;
	printf("%d\n",ans);
	for(int i=1;i<=m;++i)if(!vis[i])printf("%d\n",i);
	return 0;
}

  

原文地址:https://www.cnblogs.com/zzyer/p/8454915.html

时间: 2024-11-08 21:41:50

BZOJ 3751 [NOIP2014]解方程的相关文章

[BZOJ 3751][NOIP2014]解方程(哈希)

Description 已知多项式方程: a0+a1*x+a2*x^2+...+an*x^n=0 求这个方程在[1,m]内的整数解(n和m均为正整数). Solution 一道很久很久以前就应该做的noip的题 一定要放上来是要见证我人品崩坏的一下午 生无可恋…QAQ 题解其实也很简单啦 随便找几个素数取模验证是不是等于0就好了 随便 随便 随便 随便找几个…素数 在WA\TLE\OLE间切换,最后还是抄了别人的几个素数 怀疑人生[望天 (BZOJ上的数据是加强了的,如果是ccf的数据那当然就随

【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解方程

题目:求一个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)

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]解方程 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 解方程

描述 已知多项式方程: a0+a1x+a2x2+...+anxn=0a0+a1x+a2x2+...+anxn=0 求这个方程在[1, m]内的整数解(n 和 m 均为正整数). 格式 输入格式 输入共 n+2 行. 第一行包含 2 个整数 n.m,每两个整数之间用一个空格隔开. 接下来的 n+1 行每行包含一个整数,依次为a0,a1,a2,...,ana0,a1,a2,...,an. 输出格式 第一行输出方程在[1, m]内的整数解的个数. 接下来每行一个整数,按照从小到大的顺序依次输出方程在[

【秦九韶算法】【字符串哈希】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>