bzoj 3751: [NOIP2014]解方程

Description

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

解题报告:

这题比较诡,看到高精度做不了,就要想到取模,然后很容易发现是有问题的,所以要多取几个增加正确性,然后就开始枚举解,对于合法的解一定是对所有你选的质数都成立。
对于求这个多项式的值可以用秦九韶算法,这里不多做赘述.

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#define RG register
#define il inline
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
const int N=105,M=1000005;
int pri[6]={30011,11261,14843,19997,10007,21893},n,m,a[N][6];
bool vis[M/10][6];
void gi(int i){
   char ch=getchar();int f=1;
   while(ch>'9' || ch<'0'){
      if(ch=='-')f=-1;ch=getchar();
   }
   while(ch>='0' && ch<='9'){
      for(int k=0;k<6;k++)
         a[i][k]=a[i][k]*10+ch-48,a[i][k]%=pri[k];
      ch=getchar();
   }
   for(int k=0;k<6;k++)a[i][k]*=f;
}
int ans[M],num=0;
bool judge(int x,int k){
   int ret=0;
   for(int i=n;i>=1;i--)
      ret=x*ret%pri[k]+a[i][k],ret%=pri[k];
   return ret==0;
}
bool check(int x){
   for(int i=0;i<6;i++)
      if(vis[x%pri[i]][i]==0)return false;
   return true;
}
void work()
{
   scanf("%d%d",&n,&m);n++;
   for(int i=1;i<=n;i++)gi(i);
   for(int i=0;i<6;i++)
      for(int j=0;j<pri[i];j++)
         vis[j][i]=judge(j,i);
   for(int i=1;i<=m;i++)
      if(check(i))ans[++num]=i;
   printf("%d\n",num);
   for(int i=1;i<=num;i++)printf("%d\n",ans[i]);
}

int main(){work();return 0;}

posted @ 2017-10-02 19:53  PIPIBoss  阅读(169)  评论(0编辑  收藏  举报