• BZOJ(2) 1041: [HAOI2008]圆上的整点


    1041: [HAOI2008]圆上的整点

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 4966  Solved: 2258
    [Submit][Status][Discuss]

    Description

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

    Input

    只有一个正整数n,n<=2000 000 000

    Output

    整点个数

    Sample Input

    4

    Sample Output

    4

    HINT

    Source

    思路:看一眼题目,感觉可做。然后开始想思路,想着想着发现不可做,所以就写了个暴力。

    这是第一个:

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    long long n;
    long long ans;
    int main(){
        scanf("%lld",&n);
        int now=sqrt(n);
        long long maxn=n*n;
        for(int i=0;i<=n;i++){
            long long k=i*i;
            long long z=maxn-k,s=sqrt(z);
            if(s*s!=z)    continue;
            if(k!=0&&s!=0)    ans+=4;
            else ans+=2;
        }
        cout<<ans;
    }

    后来看了一下题解里的视频,想了想,感觉很有道理,就开始了第二次奋斗历程。
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    long long n;
    long long ans=1,sum;
    int p[1000001],c[1000001];
    int main(){
        scanf("%lld",&n);
        int m=n*n;
        for(int i=2;i<=n;i++)
            if(m%i==0){
                p[++sum]=i;
                while(m%i==0) m/=i,c[sum]++;
            }
        if(m>1){ p[++sum]=m;c[sum]++; }
        for(int i=1;i<=sum;i++)    cout<<p[i]<<" "<<c[i]<<endl;
        for(int i=1;i<=sum;i++){
            if(p[i]%2==0)    continue;
            else if(p[i]%4==1)    ans*=c[i];
            else if(p[i]%4==3&&c[i]%2!=0)    ans=0;
        }
        if(ans==0){ printf("0
    ");return 0; }
        else if(ans==1){ printf("4
    ");return 0; }
        else cout<<ans*4+4;
    }

    结果发现,调试忘记注释了。。。

    只有某个奇怪的点得分了。。。

    然后我就以为我把调试注释以后,就能AC4个点。然并卵,还是20分。

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    long long n;
    long long ans=1,sum;
    int p[10000001],c[10000001];
    int main(){
        scanf("%lld",&n);
        int m=n*n;
        for(long long i=2;i<=n;i++)
            if(m%i==0){
                p[++sum]=i;
                while(m%i==0) m/=i,c[sum]++;
            }
        if(m>1){ p[++sum]=m;c[sum]++; }
    //    for(int i=1;i<=sum;i++)    cout<<p[i]<<" "<<c[i]<<endl;
        for(int i=1;i<=sum;i++){
            if(p[i]%2==0)    continue;
            else if(p[i]%4==1)    ans*=c[i];
            else if(p[i]%4==3&&c[i]%2!=0)    ans=0;
        }
        if(ans==0){ printf("0
    ");return 0; }
        else if(ans==1){ printf("4
    ");return 0; }
        else cout<<ans*4+4;
    }

    最后,终于胜利了!!

     这是对上一个代码的优化。

    首先 先把n的因数中的2都消去,因为2对答案并没有贡献。

    其次 一个数 n*n=n^2 可以因式分解n^2=p1a1*2*p2a1*2*p3a3*2*......

    所以,因式分解后的质数,如果模4后余1那ans=ans*(ai*2+1);最后ans*4。

    还有自身是%4=1的质数的情况特判一下。ans=ans*(1*2+1)=ans*3;

    然后输出就好了。

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int ans=4;
    int n,sum=1;
    int main(){
        scanf("%d",&n);
        while((n&1)^1)    n>>=1;
        while(sum*sum<=n)    sum++;
        for(int i=2;i<=sum;i++)
            if(n%i==0){
                int tmp=0;
                while(n%i==0){ n/=i;tmp+=2; }
                if(i%4==1)    ans=ans*(tmp+1);
            }
        if(n>1&&n%4==1)    ans*=3;
        printf("%d",ans);
    }
    细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。 雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。
  • 相关阅读:
    netty ByteToMessageDecoder 分析
    netty 编/解码处理
    MAC 入门
    netty 学习
    php ioc and web rest design
    spring 启动流程
    淘宝美衣人
    ecslipe cdt lib link
    阿里巴巴中间件团队招人了!
    架构师速成-架构目标之伸缩性安全性
  • 原文地址:https://www.cnblogs.com/cangT-Tlan/p/9097539.html
Copyright © 2020-2023  润新知