zoukankan      html  css  js  c++  java
  • 棋盘覆盖(一) ACM

    棋盘覆盖

    描述

    在一个2k×2k(1<=k<=100)的棋盘中恰有一方格被覆盖,如图1(k=2时),现用一缺角的2×2方格(图2为其中缺右下角的一个),去覆盖2k×2k未被覆盖过的方格,求需要类似图2方格总的个数s。如k=1时,s=1;k=2时,s=5

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     


     

     

     

     
     
    输入
    第一行m表示有m组测试数据;
    每一组测试数据的第一行有一个整数数k;
    输出
    输出所需个数s;
    样例输入
    3
    1
    2
    3
    样例输出
    1
    5
    21

    错误答案:   读完题后,首先就想到可以用 num = (2^k * 2^k - 1) / 3,轻松算出答案。于是就有了下面的程序,写完后才发现,这个题有坑!2^100次方这个数已经超过了整数变量的最大值,这个题应该用大数算法。

    using namespace std;
    int main()
    {
        int time, k;
        cin >> time;
        int nums[time];
        int i = time;
        while (i--) {
            cin >> k;
            nums[i] = ((1 << k) * (1 << k) - 1) / 3;
        }
        i = time;
        while(i--) {
            cout << nums[i] << endl;
        }
        return 0;
    }

    大数算法,简单说就是用数组来存储数值。而相应的进位等计算操作就需要手动编写。利用数组进行大数的加减乘等操作相对简单,但是除法就麻烦多了。num = (2^k * 2^k - 1) / 3利用这个公式来算大数,显然不太明智。所以我们需要找到更好算法,充分利用计算机的循环操作。

    num = (2^4 * 2^4 - 1) / 3 = 85 = 2^6 + 2^4 + 2^2 + 2^0
    num = (2^3 * 2^3 - 1) / 3 = 21 = 2^4 + 2^2 + 2^0
    num = (2^2 * 2^2 - 1) / 3 =  5 = 2^2 + 2^0
    num = (2^1 * 2^1 - 1) / 3 =  1 = 2^0

    大家不用我说就能发现里面的规律了吧。利用这个公式就可以避免除以3的计算。

    j = k - 1

    num = 2^(2*j) + 2^(2*j-2) + …… + 2^0

    num = (((2^2 + 1) * 2^2 + 1) * 2^2 + 1) * 2^2 + 1

    可以进一步转换公式,变换成利于循环操作

    然后结合数组存储大数的方法就可以得到下面的程序

    #include<iostream>
    #include<string.h>
    using namespace std;
    
    int main()
    {
        int sum;
        cin >> sum;
        int total[sum][100];
        int n = sum;
        while(n--)
        {
            int *a = total[n];
            memset(a, 0, 100 * sizeof(int));
            int size;
            cin >> size;
            a[0] = 1;
            int i, j, k;
            for(i = 2;i <= size; ++i)
            {
                for(j = 0; j < 100; ++j)
                    a[j] = 4 * a[j];
                a[0]++;
                for(j = 0; j < 99; ++j)
                {
                    a[j+1] += a[j] / 10;
                    a[j] = a[j] % 10;
                }
            }
        }
        // 输出
        n = sum;
        while(n--)
        {
            int i, j;
            int *a = total[n];
            for(i = 99; i >= 0; --i)
                if(a[i])
                    break;
            for(j = i; j >= 0; --j)
                cout << a[j];
            cout << endl;
        }
        return 0;
    }

    另一种思路:

    如果这个题不是求L型方格的数量,而且让你绘制出摆放方格后的棋盘呢。这就变成了另外一个题,而相应的算法也完全不同。这里就需要运用分治算法。

  • 相关阅读:
    布隆过滤器
    django-redis 和 vue 实现的购物车
    富文本编辑器
    django 和 七牛云 交互
    django 提供的加密算法
    DRF mixins 的常用方法
    Python笔记5(作业)
    Python笔记5(random&sys&os模块)
    Python笔记5(collections模块)
    Python笔记5(时间模块)
  • 原文地址:https://www.cnblogs.com/sdlwlxf/p/4369774.html
Copyright © 2011-2022 走看看