zoukankan      html  css  js  c++  java
  • 2019.7.9 校内测试题 平方根

     题目

     平方根(sqrt.cpp,1s,128MB)

    【问题描述】:

      给出一个正整数 n(1<n<=2^31-1),求当 x,y 都为正整数,方程: sqrt(n)=sqrt(x)-sqrt(y) 的解中,x 的最小值是多少?

    【输入文件】:

       输入文件 sqrt.in 只有一行,一个正整数 n。

    【输出文件】:

      输出文件 sqrt.out 只有一行,即满足条件的最小的 x 的解。

    【输入输出样例】

       sqrt.in   4

       sqrt.out   9

    【数据规模】:

      30%的数据满足 1<n<=10000 100%的数据满足 1<n<=2^31-1。

    考试得分:  30

    主要算法 :  质数(质因数分解)

    应试策略:

    1.   看到根式sqrt(n)=sqrt(x)-sqrt(y),又因为三者都是正整数,所以x>n,数学老师经常说遇到根式就平方,但是怎样平方呢?需要分离变量吗?
    2.   首先将等式进行变换,分离变量y=x+n-2*sqrt(x*n),又因为y为整数,所以sqrt(x*n)也为整数
    3.        n是已知量,从小到大枚举x就可以算出sqrt(x*n)是否是整数就行
    4.        符合条件就过河拆桥式输出    

       代码

    #include<math.h>
    #include<stdio.h>
    #include<stdlib.h>
    #define FORa(i,s,e) for(int i=s;i<=e;i++)
    #define FORs(i,s,e) for(int i=s;i>=e;i--)
    #define gc pa==pb&&(pb=(pa=buf)+fread(buf,1,10000,stdin),pa==pb)?EOF:*pa++
    #define File(name) freopen(name".in","r",stdin),freopen(name".out","w",stdout)
    
    using namespace std;
    static char buf[10000],*pa=buf,*pb=buf;
    inline int read();
    
    int n,t;
    long double p1;
    long long p2;
    int main()
    {
        File("sqrt");
        n=read();
        while(++t)
        {
            p1=n+t+2*sqrt(t*n),p2=p1;
            if(p1==p2) {printf("%lld",p2);return 0;}
        }
        printf("NO WAY!");
        return 0;
    }
    inline int read()
    {
        register int x(0);register int f(1);register char c(gc);
        while(c<'0'||c>'9') f=c=='-'?-1:1,c=gc;
        while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=gc;
        return x*f;
    }

    非完美算法:  

        照搬应试策略

    正解:

    1.   沿袭应试策略的1,2点的基础上,在判断sqrt(x*n)上进行优化
    2.        已知x*n必须是完全平方数,那么将其乘积数进行质因数分解,那么质因数的幂模2都为0
    3.        所以将已知量n进行质因数分解,把质因数的幂模2不是0的数筛选出来,将x变为筛选出数的乘积,得到一个暂时符合条件下的替补x
    4.        又因为x>n,所以在x的基础上再乘上以个平方数,直到乘积大于n就输出

      代码

    #include<math.h>
    #include<stdio.h>
    #include<stdlib.h>
    #define LL long long 
    #define FORa(i,s,e) for(LL i=s;i<=e;i++)
    #define FORs(i,s,e) for(LL i=s;i>=e;i--)
    #define gc pa==pb&&(pb=(pa=buf)+fread(buf,1,10000,stdin),pa==pb)?EOF:*pa++
    #define File(name) freopen(name".in","r",stdin),freopen(name".out","w",stdout)
    
    using namespace std;
    static char buf[10000],*pa=buf,*pb=buf;
    inline LL read();
    
    LL n,t,cnt,x=1;
    long double p1;
    long long p2;
    struct Node{
        LL p,k;
    }a[32];
    int main()
    {
        File("sqrt");
        n=read();
        LL p=n;
        FORa(i,2,sqrt(p))
        {
            LL ct=0;
            if(p%i==0)
            {
                ++cnt,a[cnt].p=i;
                while(p%i==0) ct++,p/=i;
                a[cnt].k=ct;
            }
        }
        if(p>1) a[++cnt].p=p,a[cnt].k=1;
        FORa(i,1,cnt)  if(a[i].k%2==1) x*=a[i].p;
        LL t=2;
        while(x*t*t<=n) t++;
        printf("%lld",x*t*t);  
        return 0;
    }
    inline LL read()
    {
        register LL x(0);register LL f(1);register char c(gc);
        while(c<'0'||c>'9') f=c=='-'?-1:1,c=gc;
        while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=gc;
        return x*f;
    }

    总结:

    1.   现将数学式子化为“最简式”,在根据数学基本知识思考
    2.        暴力打起来就是要快而准,但是正解至少也要思考
    3.        枚举将位置变成已知,尽可能消元

  • 相关阅读:
    java接口变量问题
    FileInputStream与BufferedInputStream的对比
    eclipse使用javaFX写一个HelloWorkld
    Windows 安装Java与配置环境变量
    asp.net core处理中文的指南
    修改release management client对应的服务器的地址
    在server2012安装tfs遇到的问题:KB2919355
    release management客户端无法连接到release management server的问题解决
    如何升级PowerShell
    VS2010下调试.NET源码
  • 原文地址:https://www.cnblogs.com/SeanOcean/p/11158277.html
Copyright © 2011-2022 走看看