zoukankan      html  css  js  c++  java
  • BZOJ 1041 圆上的整点

    Description

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

    Input

    r

    Output

    整点个数

    Sample Input

    4

    Sample Output

    4

    HINT

    n<=2000 000 000

    一下内容转自:http://blog.csdn.net/csyzcyj/article/details/10044629

            首先,最暴力的算法显而易见:枚举x轴上的每个点,带入圆的方程,检查是否算出的值是否为整点,这样的枚举量为2*N,显然过不了全点。

            然后想数学方法。

           

            

             有了上面的推理,那么实现的方法为:

             枚举d∈[1,sqrt(2R)],然后根据上述推理可知:必先判d是否为2R的一约数。

             此时d为2R的约数有两种情况:d=d或d=2R/d。

             第一种情况:d=2R/d。枚举a∈[1,sqrt(2R/2d)] <由2*a*a < 2*R/d转变来>,算出对应的b=sqrt(2R/d-a^2),检查是否此时的A,B满足:A≠B且A,B互质 <根据上面的推理可知必需满足此条件>,若是就将答案加1

             第二种情况:d=d。枚举a∈[1,sqrt(d/2)] <由2*a*a < d转变来>,算出对应的b=sqrt(d-a^2),检查是否此时的A,B满足:A≠B且A,B互质 <根据上面的推理可知必需满足此条件>,若是就将答案加1

             因为这样只算出了第一象限的情况<上面枚举时均是从1开始枚举>,根据圆的对称性,其他象限的整点数与第一象限中的整点数相同,最后,在象限轴上的4个整点未算,加上即可,那么最后答案为ans=4*第一象限整点数+4

    【时间复杂度分析】:

            枚举d:O(sqrt(2R)),然后两次枚举a:O(sqrt(d/2))+O(sqrt(R/d)),求最大公约数:O(logN)

     1 #include<algorithm>
     2 #include<cmath>
     3 #include<cstdio>
     4 #include<cstdlib>
     5 using namespace std;
     6 
     7 #define maxn 300010
     8 long long n;
     9 long long ans,prime[maxn],tot,cnt;
    10 bool exist[maxn];
    11 pair <long long,long long> use[maxn];
    12 
    13 inline long long gcd(long long a,long long b)
    14 {
    15     if (b == 0) return a;
    16     return gcd(b,a%b);
    17 }
    18 
    19 inline void ready()
    20 {
    21     long long i,j;
    22     for (i = 2;i <= 300000;++i)
    23     {
    24         if (exist[i]) continue;
    25         prime[++tot] = i;
    26         for (j = i*i;j <= 300000;j += i) exist[i] = true;
    27     }
    28 }
    29 
    30 inline void divide(long long k)
    31 {
    32     for (long long i = 1;k != 1 && i <= tot;++i)
    33         if (k % prime[i] == 0)
    34         {
    35             long long t = 0;
    36             while (k % prime[i] == 0) k/=prime[i],t++;
    37             use[++cnt] = make_pair(prime[i],t);
    38         }
    39     if (k != 1) use[++cnt] = make_pair(k,1);
    40 }
    41 
    42 inline long long calc(long long d)
    43 {
    44     long long ret = 0; d = n / d;
    45     for (long long i = 0;((i*i)<<1) <= d;++i)
    46     {
    47         long long t = sqrt((double)(d - i*i));
    48         if (t * t + i * i != d) continue;
    49         if (gcd(t,i) != 1) continue;
    50         ret++;
    51     }
    52     return ret;
    53 }
    54 
    55 inline void dfs(long long now,long long mul)
    56 {
    57     if (now > cnt)
    58     {
    59         ans += calc(mul);
    60         return;
    61     }
    62     dfs(now+1,mul);
    63     long long t1 = use[now].first,t2 = use[now].second;
    64     for (long long i = 1;i <= t2;++i) mul *= t1, dfs(now+1,mul);
    65 }
    66 
    67 int main()
    68 {
    69     freopen("1041.in","r",stdin);
    70     freopen("1041.out","w",stdout);
    71     ready();
    72     scanf("%lld",&n); n <<= 1;
    73     divide(n);
    74     dfs(1,1);
    75     (ans *= 4) -= 4;
    76     printf("%lld",ans);
    77     fclose(stdin); fclose(stdout);
    78     return 0;
    79 }
    View Code
  • 相关阅读:
    HDOJ 1202 The calculation of GPA
    HDOJ 1197 Specialized Four-Digit Numbers
    HDOJ 1196 Lowest Bit(二进制相关的简单题)
    HDOJ 1194 Beat the Spread!(简单题)
    NOIP2018游记
    CF1043
    洛谷P1280 尼克的任务
    洛谷P1155 双栈排序
    SPOJ6340 ZUMA
    chessboard
  • 原文地址:https://www.cnblogs.com/mmlz/p/4280398.html
Copyright © 2011-2022 走看看