zoukankan      html  css  js  c++  java
  • uoj20 解方程 数学

    链接:http://uoj.ac/problem/20

    题意:求出$a_0+a_1x+a_2x^2+...+a_nx^n=0$在$[1,m]$之间的所有整数根。

    肯定有很多人想要直接枚举$[1,m]$之间所有的整数来进行暴力判断……坦白地讲我最早也是这么想的……直到看见了数据范围:$|a_i| le 10^{10000}$……

    我能怎么办我也很绝望啊.jpg

    于是开始满$UOJ$找题解……挨个看完之后只能用劼司机语录表示我自己的心情了:给$vfk$、鏼鏼鏼、$Picks$、$ydc$挨个跪烂……

    首先这么大的系数,我们肯定要在一个剩余系下面进行操作……不然根本算不了……然后大概就可以暴力枚举剩余系中每个数判解了……

    但是问题来了:取膜太慢。因此,整个程序的一大难点就在于怎么样减少运行时间同时保证正确性。这几个人一人提出了一种方法:

    $Picks$:任何一个$n$次多项式系数数列$n+1$次差分到最后都会变成$0$,那么直接补够$0$,预处理出每一层差分数列第一个值,然后每次线性递推,将乘法变为加法来减少常数。

    $ydc$:容易证明任何一个根都有$x|a_0$,于是每个$p^x$,$p$为素数且不能被$a_0$整除的数的倍数都不是答案,然后问题转化为某个素数是否能把$a_0$整除,这个东西可以通过压$10^{18}$乱搞减少压力,然后瓶颈就在于判因子,我们就只预处理$10^5$以内的数,再大现场判定即可。

    鏼鏼鏼:直接用$BSGS$的思想……拿出几个大小在$sqrt{m}$左右的数并在这些剩余系之下进行操作,可以证明这样的正确率是相同的但时间复杂度却优化掉了一个$sqrt{m}$……

    我看了这么多之后还是决定用$vfk$的低端方法……

    首先我们可以发现整个程序常数全在取膜上……既然如此我们就找一个取膜可以不用膜运算的素数好了!比如说:$2147483647$!

    因为$a cdot 2^{31} + b equiv a + b pmod{2^{31} - 1}$,所以$x$和$(x & 0x7fffffff) + (x >> 31)$在膜$2147483647$下面是同余的!

    那么我们就直接用位运算代替取膜就好啦!这样可以使程序时间缩短为原来的三分之一!暴力判断完成一圈之后再随便找一个素数验证一下所有答案,就$OK$啦!

    说得轻巧……实际上还是有一些问题的……我刚开始做的时候连续爆$70$……调了一下午……最后找了$vfk$自己写的程序对比了一下,震惊地发现$vfk$在膜完$2147483647$之后只是再取了一个大素数,而我则按照鏼鏼鏼的做法找了五个小素数……改了就过了……身败名裂.jpg……

    大视野评测机太慢了这个方法在别的地方全过在这就$TLE$……

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 using namespace std;
     6 const int maxm=(int)1e6+5,maxl=10005,maxn=105;
     7 const int mod[]={2147483647,999946333};
     8 int n,m,a[maxn][maxl],anssum,isfu[maxn];unsigned long long amod[maxn];bool notans[maxm];
     9 char s[maxm];
    10 unsigned long long check(unsigned long long val)
    11 {
    12     unsigned long long y=0;
    13     for(int i=n;~i;i--)
    14     {
    15         y=y*val+amod[i];
    16         y=(y&0x7fffffff)+(y>>31);
    17     }
    18     y%=0x7fffffff;
    19     return y;
    20 }
    21 bool check(int val,int module)
    22 {
    23     val%=module;unsigned long long y=0;
    24     for(int i=n;~i;i--)
    25     {
    26         y=y*val+amod[i];
    27         y%=module;
    28     }
    29     y%=module;return y;
    30 }
    31 int haha()
    32 {
    33     // freopen("equationa.in","r",stdin);
    34     // freopen("equationa.out","w",stdout);
    35     scanf("%d%d",&n,&m);anssum=m;
    36     for(int i=0;i<=n;i++)
    37     {
    38         scanf("%s",s+1);int len=strlen(s+1);
    39         for(int j=1;j<=len;j++)
    40         {
    41             if(s[j]=='-'){isfu[i]=1;continue;}
    42             if(s[j]>='0'&&s[j]<='9')a[i][++a[i][0]]=s[j]-'0';
    43         }
    44     }
    45     for(int i=0;i<=n;i++)
    46     {
    47         amod[i]=0;
    48         for(int j=1;j<=a[i][0];j++)
    49         {
    50             amod[i]=amod[i]*10+a[i][j];
    51             amod[i]%=0x7fffffff;
    52         }
    53         amod[i]=amod[i]%0x7fffffff;
    54         if(isfu[i]&&amod[i])amod[i]=0x7fffffff-amod[i];
    55     }
    56     for(int i=1;i<=m;i++)
    57         if(check(i))anssum--,notans[i]=1;
    58     for(int t=1;t<2;t++)
    59     {
    60         for(int i=0;i<=n;i++)
    61         {
    62             amod[i]=0;
    63             for(int j=1;j<=a[i][0];j++)
    64             {
    65                 amod[i]=amod[i]*10+a[i][j];
    66                 amod[i]%=mod[t];
    67             }
    68             amod[i]%=mod[t];
    69             if(isfu[i]&&amod[i])amod[i]=mod[t]-amod[i];
    70         }
    71         for(int i=1;i<=m;i++)
    72         {
    73             if(notans[i])continue;
    74             if(notans[i%mod[t]]){anssum--,notans[i]=1;continue;}
    75             if(check(i,mod[t]))anssum--,notans[i]=1;
    76         }
    77     }
    78     printf("%d
    ",anssum);
    79     for(int i=1;i<=m;i++)
    80         if(!notans[i])printf("%d
    ",i);
    81 }
    82 int sb=haha();
    83 int main(){;}
    uoj20
  • 相关阅读:
    2018-2019-2 网络对抗技术 20165230 Exp2 后门原理与实践
    BZOJ2038: [2009国家集训队]小Z的袜子(hose)
    BZOJ3262陌上花开 树状数组+Treap
    BZOJ1468 Tree 点分治入门练习题
    BZOJ2152 聪聪可可 点分治入门
    BZOJ3506 BZOJ1552 排序机械臂 Splay区间翻转(数组版自底向上的写法)
    BZOJ3196: Tyvj 1730 二逼平衡树 (线段树 + Treap 练习题)
    ZOJ2112 Dynamic Rankings 动态区间Kth(单点修改) 线段树+Treap写法
    OO第4单元总结&课程总结
    OO第三单无总结
  • 原文地址:https://www.cnblogs.com/Loser-of-Life/p/7725282.html
Copyright © 2011-2022 走看看