2021沈阳icpc补题I 类欧几里得

队内训练2 2021沈阳icpc补题I 类欧几里得

题目链接link.

题意:给你一个H,一个M,一个A。一天有h个小时,一小时有m分钟,问你一天之内有多少时刻(分钟),时针和分针的角度差小于等于 2 π A H M \frac{2 \pi A}{HM} HM2πA.

这题开场十三分钟就有队伍过了,导致我们以为是个铜牌思维题(其实最后也只过了四五十个队),签完到就去开了这个题。如果知道类欧确实过的很快,如果不知道的话,可能就会像我们一样推出个 O ( N ) O(N) O(N)的式子,有一种能做但是又会tle的没准再想想就能想出来的错觉。和队友开了三个小时的这题导致阅读理解签到一直被耽搁最后差六分钟罚时被拽出铜牌区。收获人生第一次打铁。(当然希望也是最后一次了

沈阳忏悔录都写了不下三遍了,讲讲这题怎么做好了。讲道理还是自己太菜了,算法学的不够多,不然这题大概也算板子题了,不应该丢的。当事人:现在就是非常的后悔.jpg。

首先考虑,对于每一分钟,分针会转 2 π H H M \frac{2 \pi H }{HM} HM2πH 角度,而时针会转 2 π H M \frac{2 \pi }{HM} HM2π 角度 , 多少分钟满足二者之差小于等于 2 π A H M \frac{2 \pi A}{HM} HM2πA的角度。

题目转换为,有多少数对 ( k , i ) (k,i) (k,i)满足

i H M − A ≤ k ( H − 1 ) ≤ i H M + A iHM-A≤k(H-1)≤iHM+A iHMAk(H1)iHM+A.

其中 0 ≤ k ≤ H M 0≤k≤HM 0kHM 且k和i均为整数.

i i i 的范围搞出来,就可以用类欧几里得的板子了。类欧几里得可以在 O ( l o g n ) O(logn) O(logn)时间内快速计算出 F ( a , b , c , n ) = ∑ i = 0 n F(a,b,c,n)=\sum_{i=0}^n F(a,b,c,n)=i=0n ⌊ \lfloor a i + b c \frac{ai+b}{c} cai+b ⌋ \rfloor .

也就是说,可以理解为一条直线与 x = 0 x=0 x=0 x = n x=n x=n y = 0 y=0 y=0三条线构成的梯形中的整点数对的个数。

需要注意的是,这个 i i i 的下标是从0开始的,而我们要计算的式子两个端点比较特殊,需要拿出来单独计算。所以实际上算的应该是 i i i 在[1,H-2]范围内的答案。这里需要一个高中知识来转换一下。就是左加右减。将整个要计算的函数左移一位,然后令 n=H-3 ,再加上两个端点单独计算的就可以啦。

然后交上去你会发现在这里插入图片描述
离谱嗷。

其实是因为题目说了A是可以等于 H M 2 \frac{HM}{2} 2HM的,这样在每个区间的交界处是有可能发生重复的。所以需要特判一下,ans和HM取个min就好。

板子来源

AC代码:

#include<iostream>
#include<cstdio>
#define ll long long
#define int long long
using namespace std;

ll f(ll a, ll b, ll c, ll n) 
{
	if(!a) return b/c*(n+1);
	if(a>=c||b>=c)
	return f(a%c,b%c,c,n)+(a/c)*n*(n+1)/2+(b/c)*(n+1);
	ll m=(a*n+b)/c;
	return n*m-f(c,c-b-1,a,m-1);
}

signed main( )
{
	int h,m,a;
	scanf("%lld%lld%lld",&h,&m,&a);
	
	int ans1=f( h*m ,a+h*m, h-1 ,  h-3 );
	int ans2=f( h*m ,-a+h*m-1, h-1 , h-3 );
	int ans=ans1-ans2;

	ans=ans +1 + a/(h-1) ;
	ans=ans + a/(h-1) +1;
	ans--;
	
	ans=min(ans,h*m);
	
	printf("%lld\n",ans);
	return 0;
}
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值