Circle Lattice Points(精度要求很高)

题目链接:

D - Circle Lattice Pointsicon-default.png?t=LA92https://atcoder.jp/contests/abc191/tasks/abc191_d

 思路:

首先看到题目,感觉边界附近的整点判断容易出错,用double很容易WA,又因为题目给定小数点最多给4位,那就可以用整数代替浮点数,全部数字乘以1e4来做。然后剩下的就是简单的枚举题了,确定左右边界,找出刚好越界的上下边界,up-down-1就是当前横坐标的整点数。加起来就是答案。

代码:

#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
#define int long long 
using namespace std;
const int p = 1e4; // 处理时把所有数字都乘以1e4倍

int read(){
    string s;
    cin >> s;
    int tmp = 4; //乘以10的次数,为了保证变成整数,要乘1e4
    int res = 0; //返回值的绝对值
    bool point = false; //当前是否有小数点
    for(char ch : s){
        if(ch == '-') continue; //负号放最后处理
        if(ch == '.') point = true;
        else {
            res = res * 10 + (ch - '0');
            if(point == true) tmp--; //如果当前有小数点,乘10次数-1
        }
    }
    while(tmp-- > 0){
        res *= 10;
    }
    return s[0] == '-' ? -res : res; //处理负号
}

signed main(){
    int X = read();
    int Y = read();
    int R = read();


    int lc = X-R, rc = X+R; //左右边界
    // 左右边界取整,由于正负数取整方向不同,下面两行那样做是错的,要用while来取整(虽然有点慢)
    // if(lc % p != 0) lc = (lc/p+1)*p; //左边界向右取整
    // if(rc % p != 0) rc = rc/p*p; //右边界向左取整
    while (lc % p)
        lc++;
    while (rc % p)
        rc--;


    int up = Y, down = Y; // 上下边界
    //上下边界都取整,注意取整即可,暂时不用考虑位置
    while (up % p)
        up++; //取整
    while (down % p)
        down--;

    int ans = 0;
    for(int i=lc; i<=rc; i+=p){ // 枚举横坐标,找整点数
        int dx = abs(i-X);
        //对于上下边界,都找出"恰好越界"的整点位置
        while(dx*dx + (up-Y)*(up-Y) > R*R) up -= p;
        while(up <= Y || dx*dx + (up-Y)*(up-Y) <= R*R) up += p;
        while(dx*dx + (down-Y)*(down-Y) > R*R) down += p;
        while(down >= Y || dx*dx + (down-Y)*(down-Y) <= R*R) down -= p;
        
        int dy = (up-down-p)/p;
        if(dy > 0) ans += dy; //up和down是越界的边界,up-down-1为整点数
    }
    cout << ans << endl;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值