[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 ...
随机推荐
- 从零入门 Serverless | 一文讲透 Serverless Kubernetes 容器服务
作者 | 张维(贤维) 阿里云函数计算开发工程师 导读:Serverless Kubernetes 是以容器和 kubernetes 为基础的 Serverless 服务,它提供了一种简单易用.极致弹 ...
- ☕【Java技术指南】「编译器专题」深入分析探究“静态编译器”(JAVA\IDEA\ECJ编译器)是否可以实现代码优化?
技术分析 大家都知道Eclipse已经实现了自己的编译器,命名为 Eclipse编译器for Java (ECJ). ECJ 是 Eclipse Compiler for Java 的缩写,是 Jav ...
- .NET Core 基于Quartz的UI可视化操作组件 GZY.Quartz.MUI 简介
前言 最近在用Quartz做定时任务.虽然很方便,但是Quartz自己貌似是没有UI界面的..感觉操作起来 就很难受.. 查了一下,貌似有个UI组件 不过看了一下文档..直接给我劝退了..太麻烦了 我 ...
- Python&Selenium 数据驱动测试【unittest+ddt+xml】
一.摘要 本博文将介绍Python和Selenium做自动化测试时,基于unittest框架,借助ddt模块,使用xml文件作为测试输入. 二.xml文件 保存路径:D:\\Programs\\Pyt ...
- 锚点布局anchorlayout在kv中的引用
from kivy.app import App from kivy.uix.anchorlayout import AnchorLayout from kivy.uix.button import ...
- 机器学习:EM算法
EM算法 各类估计 最大似然估计 Maximum Likelihood Estimation,最大似然估计,即利用已知的样本结果,反推最有可能(最大概率)导致这样结果的参数值的计算过程. 直白来讲,就 ...
- 使用logstash的grok插件解析springboot日志
使用logstash的grok插件解析springboot日志 一.背景 二.解决思路 三.前置知识 四.实现步骤 1.准备测试数据 2.编写`grok`表达式 3.编写 logstash pipel ...
- 0x02
#include<bits/stdc++.h> using namespace std; int n,a[10][10],vis[10],ans,b[10][10]; inline int ...
- jmeter no-JUI执行常用命令(四)
一.常用命令简述 -n, --nongui命令行界面启动jmeter-t, --testfile {filename}jmx结尾的测试计划,支持相对路径-l, --logfile {filename} ...
- Java8新特性Stream流应用示例
Java8新特性介绍 过滤集合 List<String> newList = list.stream().filter(item -> item != null).collect(C ...