令$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. linux kill信号详解

    大家对kill -9 肯定非常熟悉,在工作中也经常用到.特别是你去重启tomcat时.可是多半看来,我们对-9的理解只是表面而已. 很少有人(包括我)认真的去了解一下 kill -n 这个n到底是什么 ...

  2. 洛谷3176 [HAOI2015]数字串拆分 (矩阵乘法+dp)

    qwq真的是一道好题qwq自己做基本是必不可能做出来的. 首先,如果这个题目只是求一个\(f\)数组的话,那就是一道裸题. 首先,根据样例 根据题目描述,我们能发现其实同样数字的不同排列,也是属于不同 ...

  3. c++-string类--insert函数

    string &insert(int p0, const char *s);--在p0位置插入字符串s string &insert(int p0, const char *s, in ...

  4. Java(8)详解Random使用

    作者:季沐测试笔记 原文地址:https://www.cnblogs.com/testero/p/15201556.html 博客主页:https://www.cnblogs.com/testero ...

  5. UE4蓝图AI角色制作(四)之Gameplay调试器

    8. 寻路网格体和Gameplay调试器 为了及时识别出AI系统中的导航问题,UE4提供了一个工具用来解决这类问题,它叫Gameplay调试器.打开项目设置,在左侧找到"引擎",然 ...

  6. java定时任务调度框架

    java定时任务目前主要有三种: Java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务.使用这种方式可以让你的程序按照某一个频度执行,但不能在 ...

  7. 在Windows上使用Docker 创建MongoDB 副本集的极简方法(翻译)

    这篇博客介绍下在Windows上使用Docker 创建MongoDB 三节点副本集的最简单的方法.以下命令需要Docker for Windows并使用Linux 容器. 1: 为每个节点创建数据卷 ...

  8. 从原理—实战分析SQL注入

    前言 SQL注入是web安全中最常见的攻击方式,SQL注入有很多方法,但如果只知道payload或只用用sqlmap,不知道原理,感觉也很难掌握,这次就总结一下我所遇到的SQL注入方法,原理分析+题目 ...

  9. .net,C#,Vb,F#,Asp,Asp.net区别以及作用和方向

    .net是平台,其他都是运行在其.NET FrameWork环境下的 C#,Vb都是语言运行在.net 平台下 Asp,Asp.net 都是用来写Web网页的,但是Asp和Asp.net有区别 Asp ...

  10. Java 将Word保存为WPS和WPT格式

    本文通过Java示例展示将Word文档(如.doc/.docx)保存为WPS和WPT格式的方法. 程序环境配置 IntelliJ IDEA 2018(jdk 1.8.0) Word Jar包:Spir ...