爱奇艺2018笔试题 SSR(A, B)个数

=====更新2================
看到一大佬的代码,10^5, 10^5 只用了100+ms。思路如下
若一个数num所需的最小数factor,使得num*factor可以被开整根号,则称factor为num的补足。(num 其实等于 sqrt^2 * factor )。
记录[1,n] 和 [1,m]中所有数字的 补足,若前者的补足等于后者的补足,这这一对数合法。 所以对于序列[1,n],我们只需保存需要的补足记录个数。
factor1[i]表示[1,n]中补足为i的数字个数;同理得factor2[i], 则结果为 Sum( factor1[i] * factor2[i] ),i in [1, max(n,m)].
import java.util.*;
import java.lang.*;
/*
in
3 8
out
5
5000 5000
26544
time: 13
10000 10000
57296
time: 17
100000 100000
714036
time: 146
 */
public class iqiyiA3 {

    public static final int MAXN = 100000 + 5;
    public static int[] sqrtsNums = new int[MAXN];
    public static int countSqrtsNums = 0;
    public static boolean[] canSqrts = new boolean[MAXN]; //优化搜索, 记录平方数
    public static int[] factor1 = new int[MAXN];  //factor1[i] 表示x的个数, x属于[1,n], 且 x = k^2 * i; //缺少因子i的数字有几个。
    public static int[] factor2 = new int[MAXN]; //同上

    public static boolean canSqrtsNum(int num) {
        int sqrt = (int) Math.sqrt(num);
        return sqrt * sqrt == num;
    }

    public static void initSqrtsNums() {
        for (int i = 1; i < MAXN; i++) {
            if ( canSqrtsNum(i) ) {
                canSqrts[i] = true;
                sqrtsNums[countSqrtsNums++] = i;
            }
        }
    }

    public static void solution(int n, int m) {
        int min = Math.min(n, m);
        int max = Math.max(n, m);

        initSqrtsNums();

        for (int i = 1; i <= min; i++) {
            if ( canSqrts[i] ) { //i可开根,则所需因子为1。
                factor1[1]++;
                continue;
            }

            int restFacor = i;
            for (int j = 1; j < countSqrtsNums; j++) {
                if ( sqrtsNums[j] > restFacor ) break;

                while( restFacor % sqrtsNums[j] == 0 ) {
                    restFacor /= sqrtsNums[j];
                }
            }
            factor1[restFacor]++;
        }

        for (int i = 1; i <= max; i++) {
            if ( canSqrts[i] ) { //i可开根,则所需因子为1。
                factor2[1]++;
                continue;
            }

            int restFacor = i;
            for (int j = 1; j < countSqrtsNums; j++) {
                if ( sqrtsNums[j] > restFacor ) break;

                while( restFacor % sqrtsNums[j] == 0 ) {
                    restFacor /= sqrtsNums[j];
                }
            }
            factor2[restFacor]++;
        }

        int ret = 0;
        for (int i = 1; i <= max; i++) {
            ret += factor1[i] * factor2[i];
        }
        System.out.println(ret);
    }

    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        int n = cin.nextInt();
        int m = cin.nextInt();

        //long startTime = System.currentTimeMillis();

        solution(n, m);

        //long endTime = System.currentTimeMillis();
        //System.out.println("time: " + (endTime - startTime) );
    }
}

===========更新1=======
自己本地测试了下,优化版本的代码还没暴力版本快(😂 写那么多都是做的无用功),java Math.sqrt操作应该效率挺高了。
不过暴力版本 n = 1e5, m = 1e5 本地IDE测试大概要38s,题目中时间限制为1s,也不能ac吧。不知道更优版本是咋做的。各路大神指导下。

暴力版本。
import java.util.*;
import java.lang.*;
/*
in
3 8
out
5

5000 5000
26544
time: 109

100000 100000
637766
time: 38195 ->38 seconds
 */
public class iqiyiA2 {


    public static boolean SSRIsInt(int num1, int num2) {
        int t = num1 * num2;
        int sqrt = (int) Math.sqrt( t );
        return sqrt * sqrt == t;
    }



    public static void solution(int n, int m) {
        if (n > m) {
            //swap
            n = n ^ m;
            m = n ^ m; //n^m^m = n
            n = n ^ m; //n^m^n = m
        }
        //System.out.println(n + " " + m);
        //init cnt; i=j have n pairs;
        int cnt = n;
        for (int i = 1; i <= n; i++) {
            for (int j = i + 1; j <= n; j++) {
                if ( SSRIsInt(i, j) ) {
                    cnt += 2;
                }
            }
        }

        for (int i = 1; i <= n; i++) {
            for (int j = n + 1; j <= m; j++) {
                if ( SSRIsInt(i, j) ) {
                    cnt++;
                }
            }
        }

        System.out.println(cnt);
    }


    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        int n = cin.nextInt();
        int m = cin.nextInt();

        long startTime = System.currentTimeMillis();

        solution(n, m);

        long endTime = System.currentTimeMillis();
        System.out.println("time: " + (endTime - startTime) );
    }
}

==原答案=============================
暴力写完,也写好了优化版本,手贱变量1,2写错了,调了好久。。。没赶上时间提交。


原代码太长,贴这里了
#爱奇艺##Java工程师#
全部评论
其实这题的优化不应该着眼于开方计算,需要换一个思路,把开方换成乘法的思路才行,算一算对于每个a,哪些b可以满足条件。
点赞 回复 分享
发布于 2017-09-10 23:01
楼主写的好复杂,70%的路过,复杂度想了一个多小时也没降下来,:-( 
点赞 回复 分享
发布于 2017-09-10 22:39
有必要那么麻烦吗。
点赞 回复 分享
发布于 2017-09-10 22:36
你这真吓人,。我的代码量是你一半。。。这道题只过了50%
点赞 回复 分享
发布于 2017-09-10 22:04
public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n=sc.nextInt(); int m=sc.nextInt(); int min=Math.min(n, m); int max=Math.max(n, m); int count=min; for(int i=1;i<=min;i++){ for(int j=i+1;j<=min;j++){ int k=(int) ((int)Math.sqrt(i)*Math.sqrt(j)); if(k*k==i*j){ count+=2; //System.out.println(i+"*"+j); } } } for(int i=1;i<=min;i++){ for(int j=min+1;j<=max;j++){ int k=(int) (Math.sqrt(i)*Math.sqrt(j)); if(k*k==i*j){ count+=1; //System.out.println(i+"*"+j); } } } System.out.println(count); } 60%,考后优化了一下,这样不知道能不能过,
点赞 回复 分享
发布于 2017-09-10 22:02
头皮发麻
点赞 回复 分享
发布于 2017-09-10 22:02
我手滑了这么久,代码真的太多了
点赞 回复 分享
发布于 2017-09-10 21:53
老铁你这代码很吓人啊
点赞 回复 分享
发布于 2017-09-10 21:41
你这代码看得我头皮发麻
点赞 回复 分享
发布于 2017-09-10 21:41

相关推荐

来,说点可能被同行“骂”的大实话。🙊当初接数字马力Offer时,朋友都说:“蚂蚁的“内包”公司?你想清楚啊!”但入职快一年后的今天,我反而对他有了不一样的看法!🔹&nbsp;是偏见?还是信息差!之前没入职之前外面都在说什么岗位低人一等这类。实际上:这种情况不可至否,不能保证每个团队都是其乐融融。但我在的部门以及我了解的周边同事都还是十分好相处的~和蚂蚁师兄师姐之间也经常开一些小玩笑。总之:身份是蚂蚁公司给的,地位是自己挣的(一个傲娇女孩的自述)。🔹&nbsp;待遇?玩的就是真实!试用期工资全额发!六点下班跑得快(早9晚6或者早10晚7,动态打卡),公积金顶格交。别听那些画饼的,到手的钱和下班的时间才是真的(都是牛马何必难为牛马)。🔹&nbsp;能不能学到技术?来了就“后悔”!我们拥有权限直通蚂蚁知识库,技术栈多到学不完。说“学不到东西”的人,来了可能后悔——后悔来晚了(哈哈哈哈,可以不学但是不能没有)!💥&nbsp;内推地址:https://app.mokahr.com/su/ueoyhg❗我的内推码:NTA6Nvs走我的内推,可以直达业务部门,面试流程更快速,进度可查!今天新放HC,之前挂过也能再战!秋招已经正式开始啦~机会就摆在这,敢不敢来试一试呢?(和我一样,做个勇敢的女孩)
下午吃泡馍:数字马力的薪资一般哇,5年经验的java/测试就给人一万出头,而且刚入职第三天就让人出差,而且是出半年
帮你内推|数字马力 校招
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务