zoukankan      html  css  js  c++  java
  • 矩阵翻硬币

    问题描述

      小明先把硬币摆成了一个 n 行 m 列的矩阵。

      随后,小明对每一个硬币分别进行一次 Q 操作。

      对第x行第y列的硬币进行 Q 操作的定义:将所有第 i*x 行,第 j*y 列的硬币进行翻转。

      其中i和j为任意使操作可行的正整数,行号和列号都是从1开始。

      当小明对所有硬币都进行了一次 Q 操作后,他发现了一个奇迹——所有硬币均为正面朝上。

      小明想知道最开始有多少枚硬币是反面朝上的。于是,他向他的好朋友小M寻求帮助。

      聪明的小M告诉小明,只需要对所有硬币再进行一次Q操作,即可恢复到最开始的状态。然而小明很懒,不愿意照做。于是小明希望你给出他更好的方法。帮他计算出答案。
    输入格式
      输入数据包含一行,两个正整数 n m,含义见题目描述。
    输出格式
      输出一个正整数,表示最开始有多少枚硬币是反面朝上的。
    样例输入
    2 3
    样例输出
    1
    数据规模和约定
      对于10%的数据,n、m <= 10^3;
      对于20%的数据,n、m <= 10^7;
      对于40%的数据,n、m <= 10^15;
      对于10%的数据,n、m <= 10^1000(10的1000次方)。

    Algorithm

    很容易想到如果一个硬币被翻转了奇数次,那么它的状态就会发生改变,在这里,我们翻转奇数次的硬币就是我们之前反面朝上的硬币。

    如果一个硬币的坐标为(x, y),那么它被翻转的次数为a x b 次,若想要这个硬币被翻奇数次,a和b必须都得是奇数,即x和y都有奇数个约数。

    这个题的思路我是从这里get的,最开始我也想过要模拟,但是发现数据不允许,那么想来就一定是什么高深的数学知识或者巧妙的数据结构了。
    但是,最后发现这就是一个高精度问题 ~_~
    不过还是有点数学学问在里边,不管我之前知不知道,反正我现在是记住了:完全平方数有奇数个约数

    AC

    不知道为什么第9组数据没有通过,可能我还需要优化吧......

      1 #include<iostream>
      2 #include<string>
      3 #include<cstring>
      4 
      5 using namespace std;
      6 
      7 typedef long long ll;
      8 // MAX 有上限  85000
      9 const ll MAX = 1009;
     10 
     11 // 大数乘法 
     12 string BigMul(string x, string y)
     13 {    // 据说可以分治优化
     14     string ret;
     15     ll lenx = x.length();
     16     ll leny = y.length();
     17     // 被乘数、乘数、积 
     18     ll a[MAX], b[MAX], c[MAX];
     19     memset(a, 0, sizeof(a));
     20     memset(b, 0, sizeof(b));
     21     memset(c, 0, sizeof(c));
     22     for(ll i=lenx-1;i>=0;i--)
     23         a[lenx-i] = x[i] - '0';
     24     for(ll i=leny-1;i>=0;i--)
     25         b[leny-i] = y[i] - '0';
     26     // 第 i 位乘以 第 j 位为积的第 i+j-1 位(先不考虑进位) 
     27     for(ll i=1;i<=lenx;i++)
     28         for(ll j=1;j<=leny;j++)
     29             c[i+j-1] += a[i]*b[j];
     30     // 处理进位 
     31     for(ll i=1;i<=lenx+leny;i++)
     32         c[i+1] += c[i]/10, c[i] %= 10;
     33     // 判断第 i+j 位是否为 0  
     34     if(c[lenx+leny]) ret += c[lenx+leny] + '0';
     35     for(ll i=lenx+leny-1;i>=1;i--)
     36         ret += c[i] + '0';
     37     
     38     return ret;
     39 }
     40 
     41 // 大数比较大小 
     42 bool BigNumCmp(string a, string b)
     43 {
     44     if(a == b) return true;
     45     ll la = a.length();
     46     ll lb = b.length();
     47     if(la > lb) return true;
     48     if(la < lb) return false;
     49     for(ll i=0;i<la;i++){
     50         if(a.at(i) == b.at(i)) continue;
     51         if(a.at(i) < b.at(i)) return false;
     52         if(a.at(i) > b.at(i)) return true;
     53     }
     54 }
     55 
     56 // 大数开方 
     57 string BigSqrt(string x)
     58 {
     59     string ret;
     60     ll len = x.length();
     61     ll ls = 0, i = 0;
     62     if(len&1) ls = (len>>1) + 1;
     63     else ls = len>>1;
     64     for(ll i=0;i<ls;i++) ret += "0";
     65     if(BigMul(ret, ret) == x) return ret;
     66     while(ls--)
     67     {    
     68         for(int k=0;k<10;k++){
     69             if(BigMul(ret, ret) == x) return ret;
     70             if(!BigNumCmp(BigMul(ret, ret), x)){
     71                 ret.at(i)++;
     72                 if(ret.at(i) == ':'){
     73                     ret.at(i)--;break;
     74                 }
     75             }
     76             else{
     77                 ret.at(i)--;break;
     78             }
     79         }
     80         i++;
     81     }
     82     
     83     return ret;
     84 }
     85 
     86 int main()
     87 {
     88     string a, b;
     89     char A[2*MAX];
     90     // while(scanf("%s%s", &a[0], &b[0]))
     91     gets(A);
     92     {    
     93         int i=0;
     94         for(;i<strlen(A);i++){
     95             if(A[i] == ' '){
     96                 i++;break;
     97             }
     98             a.push_back(A[i]);
     99         }
    100         for(;i<strlen(A);i++) b.push_back(A[i]);
    101         // cout<<BigMul(a, b)<<'
    ';
    102         // cout<<BigNumCmp(a, b)<<'
    ';
    103         // cout<<BigSqrt(a)<<'
    ';
    104         // cout<<BigMul(BigSqrt(a), BigSqrt(b))<<'
    ';
    105         // puts(BigMul(BigSqrt(a), BigSqrt(b)).c_str());
    106         cout<<BigMul(BigSqrt(a), BigSqrt(b))<<'
    ';
    107     }
    108     
    109     return 0;
    110 }
    View Code

    2019-02-25

    21:20:50

  • 相关阅读:
    linux , nginx: 封禁IP的办法【转】
    分布式之消息队列复习精讲【转】
    RocketMQ 简单梳理 及 集群部署笔记【转】
    ls列出排除的文件
    patch的用法【转】
    python3.6安装 zipimport.ZipImportError: can't decompress data; zlib not available【转】
    为什么用ls和du显示出来的文件大小有差别?【转】
    Python多进程和多线程是鸡肋嘛?【转】
    nginx针对某个url限制ip访问,常用于后台访问限制【转】
    windows服务器卸载补丁命令【转】
  • 原文地址:https://www.cnblogs.com/mabeyTang/p/10433566.html
Copyright © 2011-2022 走看看