bzoj 1041: [HAOI2008]圆上的整点 【数学 思维】

题目链接:bzoj 1041: [HAOI2008]圆上的整点

题意:给定一个圆 ( x 2 + y 2 = r 2 ) (x^2+y^2=r^2) (x2+y2=r2),在圆周上有多少个点的坐标是整数。

思路:先化简
x 2 = r 2 − y 2 = ( r − y ) ∗ ( r + y ) x^2 = r^2-y^2 = (r-y) * (r+y) x2=r2y2=(ry)(r+y) 我们用 d ∗ A = ( r − y ) d*A = (r-y) dA=(ry) d ∗ B = ( r + y ) d*B = (r+y) dB=(r+y)其中 d = g c d ( r − y , r + y ) d = gcd(r-y, r+y) d=gcd(ry,r+y),限制 y > 0 y > 0 y>0
这样有 x 2 = d 2 ∗ A ∗ B x^2 =d^2*A*B x2=d2AB以及 d ∗ A + d ∗ B = 2 ∗ r d*A + d*B = 2*r dA+dB=2r r r r是已经知道的,我们就可以通过枚举因子d来构造 A + B A+B A+B的值 m m m。根据 x 2 = d 2 ∗ A ∗ B x^2 = d^2*A*B x2=d2AB A , B 互 质 A,B互质 A,B那么 A , B A,B A,B一定是完全平方数。这样得到 a 2 + b 2 = m a^2+b^2 = m a2+b2=m,再用一次枚举就可以了。

时间复杂度 O ( s q r t ( 2 ∗ r ) 2 ) O(sqrt(2*r)^2) O(sqrt(2r)2)

A C AC AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <stack>
#define PI acos(-1.0)
#define CLR(a, b) memset(a, (b), sizeof(a))
#define fi first
#define se second
#define ll o<<1
#define rr o<<1|1
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int MAXN = 2*1e6 + 1;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
void getmax(int &a, int b) {a = max(a, b); }
void getmin(int &a, int b) {a = min(a, b); }
void add(LL &x, LL y) { x += y; x %= MOD; }
LL gcd(LL a, LL b) {
    return b == 0 ? a : gcd(b, a%b);
}
bool judge(LL a, LL b, LL d, LL r) {
    LL y = r - d * a * a;
    return y > 0 && d * b * b == r + y && gcd(a, b) == 1;
}
int main()
{
    LL r; scanf("%lld", &r);
//    LL s = 0;
//    for(int x = -r; x <= r; x++) {
//        for(int y = -r; y <= r; y++) {
//            if(x * x + y * y == r * r)
//                s++;
//        }
//    }
//    printf("%lld\n", s);
    if(r == 0) {
        printf("1\n");
        return 0;
    }
    LL ans = 0;
    for(LL i = 1; i <= sqrt(2*r); i++)
    {
        if((2*r) % i == 0) {
            LL m = 2 * r / i;
            for(LL a = 1; a <= sqrt(m); a++) {
                LL B = m - a * a; LL b = sqrt(B);
                if(b * b == B) {
                    if(judge(a, b, i, r)) {
                        ans++;
                        //cout << a << " " << b << " " << i << endl;
                    }
                }
            }
            m = i;
            for(LL a = 1; a <= sqrt(m); a++) {
                LL B = m - a * a; LL b = sqrt(B);
                if(b * b == B) {
                    if(judge(a, b, 2 * r / i, r)) {
                        ans++;
                        //cout << a << " " << b << " " << 2 * r / i << endl;
                    }
                }
            }
        }
    }
    printf("%lld\n", ans * 4 + 4);
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值