[NOIP2014]解方程

3732 解方程

 

 时间限制: 1 s
 空间限制: 128000 KB
 题目等级 : 钻石 Diamond
 
 
 
题目描述  Description

输入描述  Input Description

输入文件名为equation.in。

输入共n+2行。

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

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

 

输出描述  Output Description

输出文件名为equation.out。

第一行输出方程在[1, m]内的整数解的个数。

接下来每行一个整数,按照从小到大的顺序依次输出方程在[1, m]内的一个整数解。

 

 

样例输入  Sample Input

equation.in

equation.out

2 10

1

-2

1

 

1

1

equation.in

equation.out

2 10

-3

1

 

2

1

2

 

样例输出  Sample Output

equation.in

equation.out

2 10

1

3

2

 

0

数据范围及提示  Data Size & Hint

分类标签 Tags 点此展开 
 
 
 
 1 /*
 2 嗯rp很重要.(RP++).
 3 这题是要求[1,m]区间中的合法解.
 4 然而m是一个非常大的数.
 5 不考虑精度问题枚举的话o(nm)应该是可行的
 6 (FFT压位我真是太机智了哈哈哈哈哈哈哈)
 7 (画外音:10^10000压位+处理应该会T吧orz)
 8 so我们考虑这个方程在剩余系意义下的解.
 9 (ax)%p等价于(ax+p)%p.
10 我们mod两个prime.
11 因为mod一个prime的解可能不充分. 
12 最后从[1,m]中扫一遍合法解.
13 */
14 #include<iostream>
15 #include<cstring>
16 #include<cstdio>
17 #define MAXN 201
18 #define MAXM 1000001
19 #define LL long long
20 using namespace std;
21 int n,m,ans,p[4];
22 LL a[3][MAXM];
23 bool b[MAXM];
24 char s1[MAXM];
25 void slove1(char s[],int l,int k)
26 {
27     bool flag=false;
28     int x;
29     for(int i=1;i<=2;i++)
30     {
31         x=0;
32         if(s[0]=='-') x=1,flag=true;
33         while(x<l) a[i][k]=(a[i][k]*10%p[i]+s[x]-48)%p[i],x++;
34         if(flag) a[i][k]=p[i]-a[i][k];//负数.
35     }
36 }
37 bool check(int x,int k)
38 {
39     LL tot=0,w=1;
40     for(int i=0;i<=n;i++)
41       tot=(tot+a[k][i]*w%p[k])%p[k],w=(w*x)%p[k];
42     return tot%p[k];
43 }
44 void slove()
45 {
46     for(int i=1;i<=p[1];i++)
47     {
48         if(check(i,1)) continue;
49         for(int j=i;j<=m;j+=p[1])
50           if(!check(j,2)) b[j]=true;
51     }
52     int tot=0;
53     for(int i=1;i<=m;i++)
54         if(b[i]) tot++;
55     printf("%d\n",tot);
56     for(int i=1;i<=m;i++)
57         if(b[i]) printf("%d\n",i);
58 }
59 int main()
60 {
61     p[1]=22861,p[2]=1000007977;
62     scanf("%d%d",&n,&m);
63     for(int i=0;i<=n;i++)
64     {
65         cin>>s1;
66         int l=strlen(s1);
67         slove1(s1,l,i);
68     }
69     slove();
70     return 0;
71 }

 

转载于:https://www.cnblogs.com/nancheng58/p/5784537.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值