Gym-Fisherman Broken Watch c++


Sample input 

8 4 4

7 2

3 3

4 5

5 1

2 2

1 4

8 4

9 4

6 1 4 9

Sample output

2

2

3

2

Note

The picture illustrates for the above example the area on which the third fisherman can catch fish. (上图为上面的例子所示,第三个渔民可以在这个区域捕鱼。)

 本题题意:

有n条鱼,m个渔夫,且这m个渔夫都在横坐标轴上,每个渔夫都有一个长度为l的鱼竿,当鱼和渔夫距离小于或等于l时,鱼能被钓到。

并且渔夫(x,0)与鱼(a,b)的距离(假设为L)满足如下公式   |a − x| + b.      式子中x为渔夫的横坐标,(a,b)为鱼的坐标。

求解思路:

 这道题肯定以鱼为考虑的对象。先对公式 |a − x| + b入手。设l≤|a − x| + b.可求出鱼能被钓到时渔夫x的一个范围a+l-b≤x≤a-l+b.然后把渔夫的位置排个序,遍历所有的鱼,每一条鱼能够被可以被抓都在x轴有一个范围(a+l-b≤x≤a-l+b.).通过二分,在渔夫中找到最左的和最右的,然后差分一下,最后求个前缀和就可以得出答案。(正确的思路)

网上的题解。http://www.cnblogs.com/Chen-Jr/p/9879980.html
 

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef  long long ll;
const int maxn=2e5+7;
struct fish
{
    int x,y;
}f[maxn];
struct yufu
{
    int x,id,idd;//λÖã¬ÊäÈë˳Ðò 
    bool operator <(const yufu  &bb)const
    {
        return x<bb.x;//°´Î»ÖÃÅÅÐò 
    }
}ma[maxn];
int sum[maxn],ans[maxn];
int main()
{
    int n,m,l;
    scanf("%d %d %d",&n,&m,&l);
    memset(sum,0,sizeof(sum));
    for (int i=1;i<=n;i++)
        scanf("%d %d",&f[i].x,&f[i].y);//ÊäÈëÓãµÄx y 
    for (int i=1;i<=m;i++)
    {
        scanf("%d",&ma[i].x);//ÊäÈëÓæ·òλÖà 
        ma[i].id=i;
    }
    sort(ma+1,ma+m+1);//½«Óæ·ò°´Î»ÖÃÅÅÐò 
    for (int i=1;i<=m;i++)
        ma[i].idd=i;//¼Ç¼ÐÂλÖà 
    for (int i=1;i<=n;i++)
    {
        if (f[i].y-l>0) continue;
        yufu  tmp;
        tmp.x=f[i].x-l+f[i].y;
        int xx=lower_bound(ma+1,ma+m+1,tmp)-ma;
        tmp.x=f[i].x+l-f[i].y;
        int yy=upper_bound(ma+1,ma+m+1,tmp)-ma;
        sum[xx]++;
        sum[yy]--;
    }
    for (int i=1;i<=m;i++)
    {
        sum[i]+=sum[i-1];
        ans[ma[i].id]=sum[ma[i].idd];
    }
    for (int i=1;i<=m;i++) printf("%d\n",ans[i]);
    return 0;
}

Broken Watch

Problem Description

A UFO crash lands on Earth. The alien captain survives the crash relatively unscathed; however his trusty watch is damaged beyond repair.

The alien watch is very similar to a human watch: It is a disc 30mm in diameter and it has three hands of lengths A, B and C microns (1000 ≤ A, B, C ≤ 15000). However, the aliens measure time differently: there are N (2 ≤ N &lt; 2^{32})N(2≤N<232) alien seconds to an alien minute. As such, there are N markings on the edge of the disc, rather than 60.

The watch’s glass cover is broken and the hands have come loose: they can rotate freely and independently of one another. By pointing each of the hands at an arbitrary marking, their tips can be made to form an imaginary triangle (as long as they are non-collinear).

Having nothing left to do but wait for help to arrive, the alien ponders the following question: What is the number M of distinct triangles that contain the watch’s center? (Triangles where the center lies on one of the edges of the triangle count as well.)

Input

The input consists of A, B, C, and N on a single line, separated by whitespace.

Output

The output is M modulo 2^{64}264.

Sample Input

15000 15000 15000 2
5000 10000 15000 3
15000 15000 15000 3
15000 15000 15000 4
15000 15000 15000 5
15000 15000 15000 6

Sample Output

0
6
1
4
5
14

先考虑三个针长度各不一样的情况.

注意到需要对n分奇偶性进行讨论.

n为偶数的时候,固定1号针的位置,枚举2号针的位置,那么3号针的位置就在12号针的反向延长线形成的扇形区域内(可与边界重合).并注意到当12号针反向的时候,3号针有n-2种取法.

即,n为偶数时答案为 n*(2+3+……+n/2)+n*(n-2)

奇数时答案为n*(1+2+……+[n/2])

如果三个指针都相等要除以3,有两个相等要除以2!

答案比较大,但是mod2^64可以考虑用unsigned long long

我们必须在溢出之前就把要除掉的数值给除掉。否则会造成错误答案。

//#include<bits/stdc++.h>
#include<iostream> 
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;

ull n,ans;
int a,b,c;

int main()
{
	cin>>a>>b>>c>>n;//三个指针 加刻度数 
	ull hf=n>>1;//hf=n/2 
	if(n&1)ans=hf*(hf+1); 
	else ans=((hf+1)*hf/2-1)*2+n-2;
	//等边三角形 
	if(a==b&&b==c)
	{
	    ans/=2;
	    if(ans%3==0) ans=ans/3*n;
	    else ans =n/3*ans;
	}
	//等腰三角形
	else if(a==b||a==c||b==c)
	{
		ans/=2;
		ans*=n;
	} 
	else ans*=n;
	cout<<ans<<endl;
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值