[atAGC045F]Division into Multiples
令$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的更多相关文章
- python from __future__ import division
1.在python2 中导入未来的支持的语言特征中division(精确除法),即from __future__ import division ,当我们在程序中没有导入该特征时,"/&qu ...
- [LeetCode] Evaluate Division 求除法表达式的值
Equations are given in the format A / B = k, where A and B are variables represented as strings, and ...
- 关于分工的思考 (Thoughts on Division of Labor)
Did you ever have the feeling that adding people doesn't help in software development? Did you ever ...
- 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 ...
- POJ 3140 Contestants Division 树形DP
Contestants Division Description In the new ACM-ICPC Regional Contest, a special monitoring and su ...
- 【算法题】Multiples of 3 and 5
Multiples of 3 and 5 原题 题意如下: 找出N以内的3和5的倍数的和. 思路 1.刚看到觉得好弱智,直接遍历一遍不就OK了吗?但是第2和第3个测试用例报了TLE,超时. 2.然后想 ...
- 暴力枚举 UVA 725 Division
题目传送门 /* 暴力:对于每一个数都判断,是否数字全都使用过一遍 */ #include <cstdio> #include <iostream> #include < ...
- GDC2016【全境封锁(Tom Clancy's The Division)】对为何对应Eye Tracked System,以及各种优点的演讲报告
GDC2016[全境封锁(Tom Clancy's The Division)]对为何对应Eye Tracked System,以及各种优点的演讲报告 原文 4Gamer編集部:松本隆一 http:/ ...
- Leetcode: Evaluate Division
Equations are given in the format A / B = k, where A and B are variables represented as strings, and ...
随机推荐
- SAE助力南瓜电影7天内全面Severless
作者:李刚(寻如),阿里云解决方案架构师 南瓜电影APP是国内领先的专注于影视精品化运营的垂直类视频产品,在移动互联网.IPTV.OTT等客户端,面向广大中产阶级精英群体,提供有异于院线及其他视频平台 ...
- Java初步学习——2021.10.10每日总结,第五周周日
(1)今天做了什么: (2)明天准备做什么? (3)遇到的问题,如何解决? 今天继续学习菜鸟教程java字符串实例 5.字符串反转--reverse方法 public class Main { pub ...
- 用C++实现的数独解题程序 SudokuSolver 2.4 及实例分析
SudokuSolver 2.4 程序实现 本次版本实现了 用C++实现的数独解题程序 SudokuSolver 2.3 及实例分析 里发现的第三个不完全收缩 grp 算法 thirdGreenWor ...
- go-zero 实战之 blog 系统
go-zero 实战项目:blog 本文以 blog 的网站后台为例,着重介绍一下如何使用 go-zero 开发 blog 的用户模块. 本文涉及的所有资料都已上传 github 仓库 kougazh ...
- 分布式表示(Distributed Representation)
NLP模型笔记 - 分布式表示 ziuno 2020-03-08 19:52:50 410 收藏 2 分类专栏: NLP 模型 笔记 文章标签: nlp 最后发布:2020-03-08 19:52:5 ...
- [no_code][Alpha]事后分析
$( "#cnblogs_post_body" ).catalog() 设想和目标 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 我们要解决的 ...
- 运维常用python库&模块
sutil:是一个跨平台库(https://github.com/giampaolo/psutil)能够实现获取系统运行的进程和系统利用率(内存,CPU,磁盘,网络等),主要用于系统监控,分析和系统资 ...
- Noip模拟84 2021.10.27
以后估计都是用\(markdown\)来写了,可能风格会有变化 T1 宝藏 这两天老是会的题打不对,还是要细心... 考场上打的是维护\(set\)的做法,但是是最后才想出来的,没有维护对于是没有交. ...
- Noip模拟63 2021.9.27(考场惊现无限之环)
T1 电压机制 把题目转化为找那些边只被奇数环包含. 这样的话直接$dfs$生成一棵树,给每个点附上一个深度,根据其他的非树边都是返祖边 可以算出环内边的数量$dep[x]-dep[y]+1$,然后判 ...
- Noip模拟46 2021.8.23
给了签到题,但除了签到题其他的什么也不会.... T1 数数 人均$AC$,没什么好说的,就是排个序,然后双指针交换着往中间移 1 #include<bits/stdc++.h> 2 #d ...