令$d=\gcd(a,b)$,可以发现$c|(ax+by)$等价于$lcm(c,d)|(ax+by)$,因此不妨令$c'=lcm(c,d)$,然后将$a$、$b$和$c$同时除以$d$

接下来设$(a,c)=d_{1}$,根据整除的传递性有$d_{1}|(ax+by)$,由于$d_{1}|ax$,可得$d_{1}|by$,又因为$(b,d_{1})=1$,所以$d_{1}|y$

因此,可以令$y'=\lfloor\frac{y}{d}\rfloor$,然后再将$a$和$c$同除以$d_{1}$,$b$和$c$类似,最后可以令$a$、$b$和$c$两两互素

令$D\equiv \frac{a}{b}(mod\ c)$(由于$(b,c)=1$因此存在),对于$ax+by\equiv 0(mod\ c)$,可得$y\equiv -xD(mod\ c)$,取其中最小非负整数解为$Y_{x}$(特别的,当$x=0$时取$Y_{x}=c$)

$x$的范围为$[0,c]$,同时对于$x_{1}<x_{2}$,若$Y_{x_{1}}\le Y_{x_{2}}$则后者没有意义,可以通过维护一个栈,从小到大枚举$x$,若栈顶小于$Y_{x}$则将$Y_{x}$加入栈中

构造:对于一个二维平面,有一个点$(x',y')$(初始为$(0,0)$),每一次令$x'$和$y'$分别加1,然后若$x'>c$则$x'$减去$c$,若$y'\ge D$(注意等号不同)则$y'$减去$D$

当$y'=0$时,其实就对应于$x=\frac{times}{D}$和$Y_{x}=c-x'$(其中$times$为加1的次数),前者依次遍历所有$x$,因此即若$c-x'$小于栈顶时就将$c-x'$压入栈中

但此时这样的复杂度反而退化为$o(cD)$,因此考虑递归缩小$c$和$D$的范围

注意到这样两个性质:

1.当我们位于$(x',y')$,若$x'>0$且$y'+c<D$,则$c$步后必然移动到$(x',y'+c)$,由此可以令$D$不断减去$c$直至$D\le c$

注意两个细节:1.当$x'=0$,$c$步后会移动到$(c,y'+D)$;2.当$c=D$时不能减,原因同上

2.当我们位于$(x',y')$,若$x'+D\le c$且$c-(x'+D-y')$不小于栈顶则$D$步后会移动到$(x'+D,y')$,因此考虑令$t=\lfloor\frac{c}{D}\rfloor$,当$c-tD$加入栈后,可以看作$c'=c-tD$的子问题

简单模拟前面几步,不难发现一开始栈中会插入$c,c-D,...,c-tD$,因此先将这个插入后即可缩小$c$

(这里的栈其实是有重复元素的,这次的$c-tD$和下一次的$c'$是相同的,暂时看作两个不同的数)

这就是一个欧几里得的过程,因此复杂度为$o(\log_{2}c)$,且栈中至多有$o(\log_{2}c)$个等差序列(由于复杂度限制,这个栈需要通过若干个等差数列来描述)

(另外这样的过程并不容易维护$times$,但可以通过$Y_{x}$来找到最小的$x$,即$x\equiv -\frac{Y_{x}}{D}(mod\ c)$)

有两个结论:1.对于一个等差数列,由$Y_{x}$所构造出来的$x$也是等差数列;2.$x$和$Y_{x}$的等差数列公差严格单调递增(注意$Y_{x}$为负数)

由这些结论,当我们必然存在一组最优解使得取得所有组都在同一个等差数列中

反证法,假设取了第$i$个等差数列中第$i'$项和第$j$个等差数列中第$j'$项的组合(其中$i<j$),由于$i$的末尾=$i+1$的开头($j$的开头=$j-1$的末尾),强制$i'$($j'$)不能为等差数列中最后一项(第一项)

此时,不妨令$i'$取该等差数列的后一项,$j'$取该等差数列中前一项,分别对$x$和$y$分析:记$i$和$j$两个等差数列中$x$的公差分别为$d_{i}$和$d_{j}$,相比较而言$\Delta x=d_{i}-d_{j}<0$,因此更优($y$同理)

对于一个等差数列中,可以二分枚举答案,先取等差数列中第一个,之后调整一定是$x+=d_{x}$且$y-=d_{y}$(这里的$x$和$y$只所需的数量,不是限制),最多调整$ans\cdot (len-1)$($len$为等差数列长度),简单判定即可

 1 #include<bits/stdc++.h>
2 using namespace std;
3 #define ll long long
4 int t,a,x,b,y,c,d,s,D,inv_D,ans;
5 int gcd(int x,int y){
6 if (!y)return x;
7 return gcd(y,x%y);
8 }
9 int exgcd(int a,int b,int &x,int &y){
10 if (!b){
11 x=1;
12 y=0;
13 return a;
14 }
15 int d=exgcd(b,a%b,y,x);
16 y-=(a/b)*x;
17 return d;
18 }
19 int inv(int k,int p){
20 int x,y;
21 exgcd(k,p,x,y);
22 return (x%p+p)%p;
23 }
24 ll div1(ll x,int y){
25 //t*y>=x
26 if (x<=0)return 0;
27 return (x+y-1)/y;
28 }
29 ll div2(ll x,int y){
30 if (x<0)return -1;
31 return x/y;
32 }
33 int query(int ay,int dy,int cnt){
34 int ax=c-1LL*ay*inv_D%c;
35 if (ay)ax%=c;
36 int dx=1LL*dy*inv_D%c;
37 int l=0,r=x+y;
38 while (l<r){
39 int mid=(l+r+1>>1);
40 //存在t使得ax*mid+t*dx<=x,ay*mid-t*dy<=y,0<=t<=cnt*mid
41 if (div1(1LL*ay*mid-y,dy)<=min(div2(x-1LL*ax*mid,dx),1LL*cnt*mid))l=mid;
42 else r=mid-1;
43 }
44 return l;
45 }
46 int main(){
47 scanf("%d",&t);
48 while (t--){
49 scanf("%d%d%d%d%d",&a,&x,&b,&y,&c);
50 d=gcd(a,b);
51 c/=gcd(c,d),a/=d,b/=d;
52 d=gcd(a,c);
53 y/=d,a/=d,c/=d;
54 d=gcd(b,c);
55 x/=d,b/=d,c/=d;
56 if (c==1){
57 printf("%d\n",x+y);
58 continue;
59 }
60 D=1LL*a*inv(b,c)%c;
61 inv_D=inv(D,c);
62 int cc=c,dd=D;
63 ans=0;
64 while (cc){
65 if (cc<dd)dd=(dd-1)%cc+1;
66 else{
67 int t=cc/dd;
68 ans=max(ans,query(cc,dd,t));
69 cc-=t*dd;
70 }
71 }
72 printf("%d\n",ans);
73 }
74 }

[atAGC045F]Division into Multiples的更多相关文章

  1. python from __future__ import division

    1.在python2 中导入未来的支持的语言特征中division(精确除法),即from __future__ import division ,当我们在程序中没有导入该特征时,"/&qu ...

  2. [LeetCode] Evaluate Division 求除法表达式的值

    Equations are given in the format A / B = k, where A and B are variables represented as strings, and ...

  3. 关于分工的思考 (Thoughts on Division of Labor)

    Did you ever have the feeling that adding people doesn't help in software development? Did you ever ...

  4. Multiples of 3 and 5

    #include<stdio.h> int main(void){ int n1, n2,n3; n1=333*(3+999)/2; n2=199*(5+995)/2; n3=66*(15 ...

  5. POJ 3140 Contestants Division 树形DP

    Contestants Division   Description In the new ACM-ICPC Regional Contest, a special monitoring and su ...

  6. 【算法题】Multiples of 3 and 5

    Multiples of 3 and 5 原题 题意如下: 找出N以内的3和5的倍数的和. 思路 1.刚看到觉得好弱智,直接遍历一遍不就OK了吗?但是第2和第3个测试用例报了TLE,超时. 2.然后想 ...

  7. 暴力枚举 UVA 725 Division

    题目传送门 /* 暴力:对于每一个数都判断,是否数字全都使用过一遍 */ #include <cstdio> #include <iostream> #include < ...

  8. GDC2016【全境封锁(Tom Clancy's The Division)】对为何对应Eye Tracked System,以及各种优点的演讲报告

    GDC2016[全境封锁(Tom Clancy's The Division)]对为何对应Eye Tracked System,以及各种优点的演讲报告 原文 4Gamer編集部:松本隆一 http:/ ...

  9. Leetcode: Evaluate Division

    Equations are given in the format A / B = k, where A and B are variables represented as strings, and ...

随机推荐

  1. IIS部署WCF详细教程

    前言: 前段时间接手了公司一个十几年前的老项目,该项目对外提供的服务使用的是WCF进行通信的.因为需要其他项目需要频繁的使用该WCF服务,所以我决定把这个WCF部署到IIS中避免每次调试运行查看效果. ...

  2. Apache ShardingSphere:由开源驱动的分布式数据库中间件生态

    2021 年 7 月 21 日 2021 亚马逊云科技中国峰会现场,SphereEx 联合创始人.Apache ShardingSphere PMC 潘娟受邀参与此次峰会,以<Apache Sh ...

  3. bzoj1972 SDOI2010-----猪国杀(模拟)

    题目自己去找吧 记得数据范围是<=10 注意事项: 1.牌库空的时候,要不断的抽第一张牌 2.反贼的决斗永远是向主公发的 3.每次判定无懈的时候,都是从使用锦囊的那个牌开始,记得敌意和殷勤的判断 ...

  4. SpringBoot-语言国际化

    在resouce下新建i18ni18n 类似的还有k8s在i18n下新建signIn.properties再新建 signIn_zh_CN.properties此时,iden会帮助合并: 现在可以在这 ...

  5. 串的模式匹配 BF算法和KMP算法

    设有主串s和子串t,子串t的定位就是要在主串中找到一个与子串t相等的子串.通常把主串s称为目标串,把子串t称为模式串,因此定位也称为模式匹配. 模式匹配成功是指在目标串s中找到一个模式串t: 不成功则 ...

  6. Linux Manual

    man 命令用来访问存储在Linux系统上的手册页面.在想要查找的工具的名称前面输入man命 令,就可以找到那个工具相应的手册条目. 手册页不是唯一的参考资料.还有另一种叫作 info 页面的信息.可 ...

  7. MyBatis的框架设计

    1.MyBatis的框架设计 2.整体设计 2.1 总体流程 (1)加载配置并初始化       触发条件:加载配置文件 配置来源于两个地方,一处是配置文件,一处是Java代码的注解,将SQL的配置信 ...

  8. spring cloud config 结合 spring cloud bus实现配置自定的刷新

    在线上环境中,有时候我们希望系统中的某些配置参数在修改后,可以立即生效而不用重新启动服务.由上一节我们知道,我们可以把配置文件统一放到配置服务中进行管理,这一节我们在配置中心中整合spring clo ...

  9. 零基础入门之Linux进程基础

    计算机实际上可以做的事情实质上非常简单,比如计算两个数的和,再比如在内存中寻找到某个地址等等.这些最基础的计算机动作被称为指令(instruction).所谓的程序(program),就是这样一系列指 ...

  10. Hadoop的安装与部署

    一.硬件及环境 服务器:3台,IP分别为:192.168.100.105.192.168.100.110.192.168.100.115 操作系统:Ubuntu Server 18.04 JDK:1. ...