题目链接:
D - Circle Lattice Pointshttps://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;
}