[F][2]NOIP 2014 解方程

来源:互联网 发布:网络广告费价格 编辑:程序博客网 时间:2024/05/18 00:09

题目描述

已知多项式方程:

a0+a1x+a2x^2+..+anx^n=0

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

输入输出格式

输入格式:
输入文件名为equation .in。

输入共n + 2 行。

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

接下来的n+1 行每行包含一个整数,依次为a0,a1,a2..an

输出格式:
输出文件名为equation .out 。

第一行输出方程在[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%:0 < n<=2,|ai|<=100,an!=0,m<100

50%:0 < n<=100,|ai|<=10^100,an!=0,m<100

70%:0 < n<=100,|ai|<=10^10000,an!=0,m<10000

100%:0 < n<=100,|ai|<=10^10000,an!=0,m<1000000


【分析】
好神奇啊
玄学取mod大法
如果我们模的数字是k。左边式子带入x和带入x+k是没有区别的。如果我们把质数k取得小一些,这样x就不用试1~m,而是试1~k。这样复杂度就变成了O(nkprime),如果k取10^4左右就完全没有问题。


【代码】

//NOIP 2014 解方程 #include<cmath>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#define ll long long#define M(a) memset(a,0,sizeof a)#define fo(i,j,k) for(i=j;i<=k;i++)using namespace std;int n,m;int mod[6]={0,22861,22871,22877,22901,22907};int dp[105][10]; //就是爱把变量名设为dp int ans[1000005];int main(){    int i,j,k;    scanf("%d%d",&n,&m);    fo(i,0,n)    {        int mul=1,st=0;        char ch[10005];        scanf("%s",ch);        int len=strlen(ch)-1;        if(ch[0]=='-') mul=-1,st++;        fo(j,st,len)          fo(k,1,5)            dp[i][k]=(dp[i][k]*10+ch[j]-'0')%mod[k];        fo(k,1,5) dp[i][k]*=mul;    }    bool flag[1000005];    memset(flag,1,sizeof flag);    fo(i,1,m)  //枚举解       if(flag[i])      {          bool root=1;          for(j=1;root && j<=5;j++)          {              ll val=dp[0][j],x=i%mod[j];              fo(k,1,n)              {                  val=(val+dp[k][j]*x%mod[j])%mod[j];                  x=i*x%mod[j];  //递推x^k                      }              if(val)              {                  root=0;                  for(k=i;k<=m;k+=mod[j])                    flag[k]=0;              }          }          if(root) ans[++ans[0]]=i;      }    fo(i,0,ans[0]) printf("%d\n",ans[i]);    return 0;}
0 0
原创粉丝点击