noip2014解方程解题报告
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了noip2014解方程解题报告相关的知识,希望对你有一定的参考价值。
看到大佬在写,,顺手就去看了看
简单思考后,还是只会打暴力,就去看了题解qwq
cogs是图片,于是从bzoj上粘了一份。题目是有部分分的详细可看链接
3751: [NOIP2014]解方程
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 3788 Solved: 809
[Submit][Status][Discuss]
Description
已知多项式方程:
Input
Output
第一行输出方程在[1,m]内的整数解的个数。
Sample Input
2
-3
1
Sample Output
1
2
HINT
对于100%的数据,0<n≤100,|ai|≤1010000,an≠0,m≤1000000。
对于30%的数据,怕是为了不让大家爆0而设定的,只需要枚举1到m所有x的可能值带进去一一检验即可。O(n^2*m)
对于50%的数据,我们可以打个高精度,枚举即可过掉,但是需要注意,此时带入求方程的值不能暴力求了,而是要用秦九韶算法来求。O(n*m*len),len表示高精度的位数
对于其他的数据,操作就比较sao了。
如果a=0,那么a%b=0,这是显然的,但是如果a%b=0,那么a=0,这显然是不对的,不过当b取很多个数的时候并且a%b=0都成立时,a“几乎”就等于0了,a不是0的概率会非常小,于是我们可以把他当做0。
那么我们就可以取几个素数,分别让ai对于他们依次取模(因为ai太大了,所以取模操作是在读入的时候完成,类似于高精度),然后枚举每一个x∈[1,m],边乘边取模,如果对于几个模数最终得到的结果都为0,那么我们认为x为当前方程解之一。
但是我们计算一下复杂度,n*m大概,而且要大于n*m。显然无法过掉100%的数据。那么我们需要再想一些方法。
我们知道,(a*b)%p==(a%p*b)%p,那么如果当前x∈[1,p[1]],并且x是方程的一个解,那么x+p[1]也是方程的一个解。
于是我们就将复杂度降了下来,至于是多少我也不会算啊...反正会远(shao)小于n*m,而如果模数取得很大,就无法实现这个优化,所以模数不能取很大,p[1]取10000左右就可以了
下面是我的代码。
1 #include<bits/stdc++.h>//好神奇!考场能拿50就上天了qwq 2 #define ll long long 3 using namespace std; 4 int n,m; 5 ll a[10][105],mod[10]={0,10007,13417,16231,19441,22159,27043}; 6 void read(int x){ 7 char ch=getchar(); 8 int f=1; 9 while(!(ch<=‘9‘&&ch>=‘0‘)){ 10 if(ch==‘-‘)f=-1; 11 ch=getchar(); 12 } 13 while(ch<=‘9‘&&ch>=‘0‘){ 14 for(int i=1;i<=6;i++){ 15 a[i][x]=a[i][x]*10+ch-‘0‘; 16 if(a[i][x]>=mod[i]){ 17 a[i][x]%=mod[i]; 18 } 19 }ch=getchar(); 20 } 21 for(int i=1;i<=6;i++)a[i][x]*=f; 22 } 23 int ans; 24 bool book[1000006]; 25 int check(ll x,int z){ 26 ll ans=a[z][n]; 27 for(int i=n-1;i>=1;i--){ 28 ans=(ans*x%mod[z]+a[z][i])%mod[z]; 29 }return ans; 30 } 31 int main() 32 { 33 freopen("equationa.in","r",stdin); 34 freopen("equationa.out","w",stdout); 35 scanf("%d%d",&n,&m);n++; 36 for(int i=1;i<=n;i++){ 37 read(i); 38 } 39 for(ll i=1;i<=min(mod[1],(ll)m);i++){ 40 if(!check(i,1)){ 41 for(int j=i;j<=m;j+=mod[1])book[j]=1,ans++; 42 } 43 } 44 for(ll i=1;i<=m;i++){ 45 if(!book[i])continue; 46 int bo=0; 47 for(int j=2;j<=6;j++){ 48 if(check(i,j)){ 49 bo=1;break; 50 } 51 } 52 if(bo)book[i]=0,ans--; 53 } 54 printf("%d\n",ans); 55 for(int i=1;i<=m;i++)if(book[i])printf("%d\n",i); 56 return 0; 57 }
以上是关于noip2014解方程解题报告的主要内容,如果未能解决你的问题,请参考以下文章