• 【HAOI2008】硬币购物


    既然没人写扩欧,那我就来一发吧。

    扩欧也还好,就是跑的有点慢,然后写的时候还有点烦,不过还是卡过去了。

    考场上看到这道题又蒙了。。。
    怎么回事第一题又要爆零了?

    然后我打了个暴力测了一下极限数据根本过不去(幸好没把电脑整死机)

    于是想了又想,整出了个 $ O(s* t)$的扩欧算法(打了一个小时的样子)。

    (话说正解好像容斥)

    原本搞了下循环展开结果好像会更慢。。。


    讲一下思路:用扩欧解。

    安利扩欧博客:Judge's Class


      预处理解之前我们要先用扩欧求出:
      c1*x + c2*y = gcd(c1,c2) 中的 x和y (以及gcd),记录下来,
      然后 c1、c2 除以 gcd(c1,c2)。(会扩欧的话就能懂吧。)
      然后我们先 O(s log s) 预处理用 c1、c2 能拼出 s 的解。
      (即 c1*x1 + c2*y1 = s 中 x1和y1 的解)
      然后我们令 x1 达到最小正整数状态,即 y1 达到最大解。
      这时如果 y1 为负数,则无解,将数组中的值设为-1,break。
      否则我们用数组记录下此时的解。

      那么 c3、c4 也是同理这样处理。

      这样处理完之后我们发现如果没有 d 数组的限制,y/c2 就是方案数,
      那么我们考虑一下 d1对x1 的限制 以及 d2 对 y1 的限制求出解的方案数。
      然后记录答案在 f 数组里面,至于 c3、c4 就记录进 g 数组。
      然后 O(s) 滚出答案。

     1 //by Judge
     2 #include<bits/stdc++.h>
     3 #define rint register int
     4 #define ll long long
     5 using namespace std;
     6 const int M=1e5+5;
     7 #idndef Judge
     8 #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
     9 #endif
    10 char buf[1<<21],*p1,*p2;
    11 inline int read(){ int x=0,f=1; char c=getchar();
    12     for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    13     for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f;
    14 } int c1,c2,c3,c4,d1,d2,x11,x22,y11,y22,d[5];
    15 int X1[M],X2[M],Y1[M],Y2[M],f[M],g[M];
    16 int ex_gcd(int a,int b,int& x,int& y){ /* 套个板子,忘了就现推 */
    17     if(!b) return x=1,y=0,a;
    18     int d=ex_gcd(b,a%b,y,x);
    19     return y-=a/b*x,d;
    20 }
    21 int main(){
    22     c1=read(),c2=read();
    23     c3=read(),c4=read();
    24     d1=ex_gcd(c1,c2,x11,y11);
    25     d2=ex_gcd(c3,c4,x22,y22);
    26     c1/=d1,c2/=d1,c3/=d2,c4/=d2;
    27     /*  预处理出解  */
    28     for(rint s=1;s<=1e5;++s){
    29         rint tmp=s,x=x11,y=y11;
    30         rint a=c1,b=c2;
    31         if(tmp%d1){
    32             X1[s]=Y1[s]=-1;
    33             continue;
    34         }
    35         tmp/=d1,x*=tmp,y*=tmp;
    36         
    37         y+=x/b*a,x%=b;
    38         if(x<0) x+=b,y-=a;
    39         if(y>=0) X1[s]=x,Y1[s]=y;
    40         else X1[s]=Y1[s]=-1;
    41     }
    42     for(rint s=1;s<=1e5;++s){
    43         rint tmp=s,x=x22,y=y22;
    44         rint a=c3,b=c4;
    45         if(tmp%d2){
    46             X2[s]=Y2[s]=-1;
    47             continue;
    48         }
    49         tmp/=d2,x*=tmp,y*=tmp;
    50         
    51         y+=x/b*a,x%=b;
    52         if(x<0) x+=b,y-=a;
    53         if(y>=0) X2[s]=x,Y2[s]=y;
    54         else X2[s]=Y2[s]=-1;
    55     }
    56     for(rint T=read(),S;T;--T){
    57         ll ans=0;
    58         for(int i=1;i<=4;++i)
    59             d[i]=read();
    60         S=read(),f[0]=g[0]=1;
    61         /*  考虑限制求出方案数  */
    62         for(rint s=1;s<=S;++s){
    63             rint tmp=s,a=c1,b=c2;
    64             rint x=X1[s],y=Y1[s];
    65             if(x<0||y<0){
    66                 f[s]=0;
    67                 continue;
    68             }
    69             rint maxX=min(x+y/a*b,d[1]);
    70             
    71             if(d[2]<y) x+=(y-d[2]+a-1)/a*b;
    72             if(x>maxX){
    73                 f[s]=0;
    74                 continue;
    75             }
    76             f[s]=(maxX-x)/b+1;
    77         }
    78         for(rint s=1;s<=S;++s){
    79             rint tmp=s,a=c3,b=c4;
    80             rint x=X2[s],y=Y2[s];
    81             if(x<0||y<0){
    82                 g[s]=0;
    83                 continue;
    84             }
    85             rint maxX=min(x+y/a*b,d[3]);
    86             
    87             if(d[4]<y) x+=(y-d[4]+a-1)/a*b;
    88             if(x>maxX){
    89                 g[s]=0;
    90                 continue;
    91             }
    92             g[s]=(maxX-x)/b+1;
    93         }
    94         /*  O(s) 滚出答案  */
    95         for(rint i=0;i<=S;++i)
    96             ans+=1ll*f[i]*g[S-i];
    97         printf("%lld
    ",ans);
    98     } return 0;
    99 }
  • 相关阅读:
    后端开发-Mybatis开发之一
    Zeppelin推荐
    构建Maven项目
    linux使用curl进行WebService接口测试
    html和jsp的区别及优缺点
    Ajax实现Web长连接
    java生成二维码
    Android调用传感器和震动
    【Head First设计模式-读书笔记】装饰者模式
    【Head First设计模式-读书笔记】观察者模式
  • 原文地址:https://www.cnblogs.com/Judge/p/9887371.html
Copyright © 2020-2023  润新知