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\n");return 0; }
    else if(ans==1){ printf("4\n");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\n");return 0; }
    else if(ans==1){ printf("4\n");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);
}

 

posted @ 2018-05-27 21:52  一蓑烟雨任生平  阅读(140)  评论(0编辑  收藏  举报