zoukankan      html  css  js  c++  java
  • 常州培训 day4 解题报告

     第一题:(简单的模拟题)

    给出一个N位二进制数,有‘+’, ‘-’, ‘*’, ‘/’ 操作,分别表示加1,减1,乘2,除以2,给出M个操作,求出M个操作后的二进制数。N,M<=5000000;

    数据保证最高位不会进位或退位。

    解题过程:

    1.一开始以为是裸的高精度,但是数据范围肯定做不到那么大。考虑二进制运算的特殊性,题目又有”数据保证最高位不会进位或退位“,那么二进制数的最高位已经定了,只要做一个尾指针r,如果*就r++,如果除就r--,就是模拟左移右移的过程。

    2.考虑到1011111111111111111111111111111的情况,如果+1,那么就要改变很多位,而N又很大,担心超时,于是做了一个累加器cnt,如果碰到‘+’,就cnt++,碰到‘-’就cnt--。碰到‘*'的时候考虑cnt的值,如果比较大(自己设一个边界),那么就先做一次加法(减法),把cnt清0;碰到除法比较恶心,需要考虑2种特殊情况;

    A.如果cnt为负奇数,且被减数x为偶数,那么 比如(10-5)/2=2, 就不能简单的把被减数和减数都除以2,因为(10/2-5/2)=3,所以需要多减一个1。

    B.如果cnt为正奇数,x是奇数,那么比如 (11+5)/2=8, 就不能简单的把x和cnt都除以2,因为(11/2+5/2)=7,所以需要多加一个1。

    这样就不用每次都处理整个数,只有当计数器累积的值比较大的时候才做一次,大大减小了计算次数。

    考试的时候处理乘法的时候,边界写错,结果爆0了。。自己写的小数据没能找出错。

    3.修改后的代码速度却很不理想,竟然不如最朴素的算法,碰到‘+’就+1,碰到‘-’就-1,碰到‘*'就右移一位,碰到’/'就左移一位。。一开始优化了半天,还是不如人家的朴素算法,最后才发现是 int 和char 速度的区别,用char 表示二进制数速度可以快一倍,不过2中的优化就没法用了。但是相比之下char比int要快的多得多。 简单才是最美额。

    另外在考试的时候发现一个非常奇妙的东西,就是对于负数,右移一位不等价于除以2. 

    (-7)/2=-3;

     (-7)>>1=-4;

    考试时百思不得其解,搜了些资料

    http://www.cnblogs.com/myblesh/articles/2431806.html

    http://wenku.baidu.com/link?url=q5qwUdt9n7VYZVVd_IyxaxuA0XXgMS__KGmx-e__0Eym8yXI1jDcrcnJO3Ac_AUvTyNLaPh-4eUkABIFTmfh1KRdSWsBE1kEJHLCkJU2oRe

    大致是 -7 的存储是用补码,也就是11111.......11001;右移一位就变成了111111....11100;转换回来就是10000....100;也就是-4。 以后碰到负数还是老老实实用‘/’吧。。

    第二题:

    题目大意:给出n*m的棋盘,给出棋盘上k个皇后(可以控制行列和对角线)的坐标,求出没有被控制的点的个数。 N,M<=50000,K<=500;

    解题过程:

    1.最容易想到的是开一个二维数组,然后依次判断每个点是否被控制,但是空间显然不够。

    2.很快能想到可以倒过来做,求出被控制的点的个数,用m*n来减就是答案。用hash数组保存每行每列以及对角线的情况,然后依次加入一个个皇后,对于每一个皇后,沿着行列和对角线走一遍,统计增加的被控制的点即可。复杂度O(nk),常数也比较小;

    3.300分的AK大神 上去讲了个思路,挺巧妙的,不过感觉效率可能还不如 2中的方法:从上往下一行行扫描,对于每一个皇后,可以求出它能控制到的这行的那些点,用一个hash并统计被控制的点的个数。。复杂度应该也是(nk),但是常数估计比较大,因为处理完每一行,hash数组都要memset一遍。

    4.讲课的大神的方法:把同一行的60个格子压成一个long long,加上hash即可。。不过感觉具体实现起来有些麻烦。

    第三题:

    题目大意:求出满足相邻数字不超过2的 K位数的个数。 K<=10^18;结果mod 1000000007;

    解题过程:

    1.这题数据太大了,30%的都是10^6;写了个动规,F[i][j]表示以i结尾的j位数的个数,F[i][j]=sum(F[k][j-1]),(i-2<=k<=i+2,0<=k<=9);

    怕超时,把递推改成记忆化了,结果爆栈,只骗到了一个k=1的数据。

    2.正解思路基本也是这样,不过要用矩阵乘法优化;参考国家集训队论文,现学了点矩阵乘法的东西。

    http://wenku.baidu.com/link?url=baFXefgWWbuE53GG3ET9Uk9XCNFsmsbOBAE-DrgWS0ahGjMKyJDVyCNBwlD_7ApyoGPVzCodMPrFPS0STyYXmGLK0iRoNZVsSbqqhzdyXWi

    只在yzoi上写了个矩阵乘法版斐波那契,算是勉强入门了。

    再来看这题,首先根据递推公式,发现 F[i][j]只和F[i-2...i+2][j] 有关,因此构造这样一个矩阵:

    1 1 1 0 0 0 0 0 0 0

    1 1 1 1 0 0 0 0 0 0

    1 1 1 1 1 0 0 0 0 0

    0 1 1 1 1 1 0 0 0 0

    0 0 1 1 1 1 1 0 0 0

    0 0 0 1 1 1 1 1 0 0

    0 0 0 0 1 1 1 1 1 0

    0 0 0 0 0 1 1 1 1 1

    0 0 0 0 0 0 1 1 1 1

    0 0 0 0 0 0 0 1 1 1

    初始矩阵为 0 1 1 1 1 1 1 1 1 1

    分别表示以i开头长度为1的 方案数。利用结合律先让 第一个矩阵自乘n-2次,再和第二个矩阵乘一次 即为答案。

     

  • 相关阅读:
    Spring Boot 配置文件 bootstrap vs application 到底有什么区别?
    一份完整的 Java 成神路线图,值得收藏!
    12 岁开始学编程,17 岁总结了 7 个重要教训!
    想成为顶尖 Java 程序员?先过了下面这些问题!
    Dubbo面试20问!这些题你都遇到过吗?
    yum安装出现No package crontabs available解决办法
    表结构设计方法
    后端token认证模板
    vue 用户登录 路由拦截 vuex cookie
    pyharm无法安装包的问题
  • 原文地址:https://www.cnblogs.com/vb4896/p/3913704.html
Copyright © 2011-2022 走看看