题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6584

题目大意:求所有满足\(0<\frac{p}{q}\leq1, gcd(p,q)=1,p\leq n,q\leq n\)的分数中,第\(k\)小的分数

题解:考虑二分答案,并用分数形式记录。假设当前二分的分数为\(\frac{p}{q}\),则小于等于这个分数的个数为

$$\sum_{i=1}^{n}\sum_{j=1}^{\left \lfloor \frac{pi}{q} \right \rfloor}[gcd(i,j)==1]=\sum_{i=1}^{n}\sum_{j=1}^{\left \lfloor \frac{pi}{q} \right \rfloor}\sum_{d|i,d|j}^{ }\mu(d)=\sum_{i=1}^{n}\sum_{d|i}^{ }\mu(d)\left \lfloor \frac{pi}{qd} \right \rfloor=\sum_{d=1}^{n}\mu(d)\sum_{i=1}^{\left \lfloor \frac{n}{d} \right \rfloor}\left \lfloor \frac{pi}{q} \right \rfloor$$

   这个式子可以通过预处理莫比乌斯函数的值,然后分块加类欧做到\(O(\sqrt{n}logn)\)的时间复杂度求解

   在二分出答案后,只需找到最小的大于等于\(\frac{p}{q}\)的分数即可。官方题解使用了\(Stern-Brocot Tree\),实际上通过枚举分母也可以做到\(O(n)\)求解

我的代码跑了7347ms...和之前的A还有K题一样极限_(:з」∠)_

 #include<bits/stdc++.h>
using namespace std;
#define N 1000001
#define LL long long
LL T,n,k,cnt,p[N],mu[N],v[N];
#undef LL
struct Frac
{
#define LL __int128
LL p,q;
void simp()
{
LL d=__gcd(p,q);
p/=d,q/=d;
}
Frac operator +(const Frac &t)const
{
Frac tmp;
tmp.q=q*t.q;
tmp.p=p*t.q+q*t.p;
tmp.simp();
return tmp;
}
Frac operator /(const LL &t)const
{
Frac tmp;
tmp.p=p;
tmp.q=q*t;
tmp.simp();
return tmp;
}
bool operator <(const Frac &t)const
{
return p*t.q<q*t.p;
}
bool operator <=(const Frac &t)const
{
return p*t.q<=q*t.p;
}
#undef LL
};
void pretype()
{
#define LL long long
mu[]=;
for(LL i=;i<N;i++)
{
if(!v[i])p[++cnt]=i,mu[i]=-;
for(LL j=;j<=cnt && i*p[j]<N;j++)
{
v[i*p[j]]=;
if(i%p[j]==)break;
mu[i*p[j]]=-mu[i];
}
}
for(LL i=;i<N;i++)
mu[i]+=mu[i-];
#undef LL
}
#define LL __int128
LL f(LL a,LL b,LL c,LL n)
{
LL m=(a*n+b)/c;
if(!a || !m)return ;
if(a>=c || b>=c)return n*(n+)/*(a/c)+(b/c)*(n+)+f(a%c,b%c,c,n);
return n*m-f(c,c-b-,a,m-);
}
LL check(Frac k)
{
LL res=;
for(LL i=;i<=n;i++)
{
LL j=n/(n/i);
res+=(mu[j]-mu[i-])*f(k.p,,k.q,n/i);
i=j;
}
return res;
}
LL ceil(LL x,LL y){return (x-)/y+;}
#undef LL
void Find(Frac k)
{
#define LL long long
Frac ans={,};
for(LL i=;i<=n;i++)
ans=min(ans,{ceil(k.p*i,k.q),i});
ans.simp();
printf("%lld/%lld\n",(LL)ans.p,(LL)ans.q);
}
void init()
{
scanf("%lld%lld",&n,&k);
Frac l={,n},r={,},mid;
while(l+(Frac){,n*n}<=r)
{
mid=(l+r)/;
if(check(mid)<k)l=mid;
else r=mid;
}
Find(l);
}
int main()
{
//freopen("test.in","r",stdin);
//freopen("test.out","w",stdout);
pretype();
scanf("%lld",&T);
while(T--)init();
return ;
}

最新文章

  1. ORA-01919
  2. 正则中关于修饰符g以及exec和match区别的一个小demo
  3. 用H5+Boostrap做简单的音乐播放器
  4. [Leetcode] Maximum Gap
  5. 蓝牙的OBEX协议
  6. Golang学习 - strings 包
  7. SecureCRT+WinSCP 共用 key pub 密钥 转换 ppk 登录ssh
  8. 在C#中使用正则表达式自动匹配并获取所需要的数据
  9. cocos2d-x项目过程记录(ios和android设备的适配)
  10. HDU_2039——判断三条边是否能组成三角形
  11. 关于EF Code First模式不同建模方式对建表产生的影响
  12. JS window对象的top、parent、opener含义介绍(转载)
  13. 使用kbmmw 实现图形验证码
  14. async+await处理异步问题
  15. oracle 两个网络不通的远程数据库如何将一个库中的表数据导入到另一个库中?
  16. HTML+CSS实现页面
  17. 监督学习——随机梯度下降算法(sgd)和批梯度下降算法(bgd)
  18. JS组件系列——JsPlumb制作流程图及相关效果详解
  19. django(新增model)No migrations to apply.
  20. 马老师 生产环境mysql主从复制、架构优化方案

热门文章

  1. python对影评进行评论分析,形成词云图
  2. Python笔记004-Python最基本内置数据类型和运算符
  3. 【全排列+子序列】Color
  4. 【5号课堂】scratch制作电子生日贺卡
  5. arcgis for android100.x 禁止地图旋转
  6. java基础知识学习 内存相关
  7. (八)Struts标签基础(一)
  8. (十一)web服务与javaweb结合(2)
  9. 本地虚拟机NAT模式下怎么设置才可以访问外网
  10. Html Agility Pack 使用 XPath 选择器