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次方)。
    解题思路:因为硬币最后都正面朝上,所以只要统计那些硬币翻了奇数次就行了。
    那么怎么求得那些硬币翻了奇数次呢?
    假如某个硬币的位置是 a行 b列。
    那么是不是存在任意的组合 i*x=a ,j*y=b。就可以翻硬币。
    易知,翻硬币的次数  times = (a的约数的个数)*(b的约数的个数)。
    易知,奇数乘奇数才能得到奇数。
    而且约数个数为奇数的数只能是平方数!
    因此最后结果为(n的开方数)*(m的开方数)。
     
    ---------------------------------------------------------------------------------------------------
     
    ps:代码通过率90%
     
    代码如下:
     
     1 #include<iostream>
     2 #include<bits/stdc++.h>
     3 #include<string>
     4 #include<string.h>
     5 #include<algorithm>
     6 #include<cmath>
     7 using namespace std;
     8 
     9 string Multstr(string str1,string str2){   //大数相乘
    10 
    11     string strResult = "";
    12     int len1 = str1.length();
    13     int len2 = str2.length();
    14     int num[500] = {0};
    15     for(int i=0;i<len1;i++){
    16         for(int j=0;j<len2;j++){
    17             num[len1-1-i+len2-1-j]+=(str1[i]-'0')*(str2[j]-'0');
    18         }
    19     }
    20     for(int i=0;i<len1+len2;i++){
    21         num[i+1]+=num[i]/10;
    22         num[i]=num[i]%10;
    23     }
    24     int a=0;
    25     for(int i=len1+len2-1;i>=0;i--){
    26         if(num[i]!=0){
    27             a=i;break;
    28         }
    29     }
    30     for(int i=a;i>=0;i--){
    31         strResult += num[i]+'0';
    32     }
    33     return strResult;
    34 }
    35 string Big_sqrt(string a){   //大数开方
    36     int alen =a.length();
    37     string asqrt="";
    38     if(alen%2==0){
    39         for(int i=0;i<alen/2;i++){
    40             asqrt+="0";
    41         }
    42     }else{
    43         for(int i=0;i<alen/2+1;i++){
    44             asqrt+="0";
    45         }
    46     }
    47     int now=0;
    48     string sum1,sum2;
    49     sum1=Multstr(asqrt,asqrt);
    50     while( alen%2==0 ? now!=alen/2 : now!=alen/2+1){
    51         string tmp1=asqrt;
    52         for(int i=0;i<9;i++){
    53             tmp1[now]=tmp1[now]+1;
    54             sum2=Multstr(tmp1,tmp1);
    55             if(sum1==a){
    56                 return asqrt;
    57             }
    58             if(sum1<=a&&sum2>a&&sum2.length()==a.length()){
    59                 break;
    60             }
    61             if(sum1<=a&&sum2.length()>a.length()){
    62                 break;
    63             }
    64             asqrt=tmp1;
    65             sum1=sum2;
    66         }
    67         now++;
    68     }
    69     return asqrt;
    70 }
    71 int main(){
    72     string a,b;
    73     cin>>a>>b;
    74     string a1,b1;
    75     a1=Big_sqrt(a);
    76     b1=Big_sqrt(b);
    77     cout<<Multstr(a1,b1)<<endl;
    78     return 0;
    79 }
     
  • 相关阅读:
    HDU 1863 畅通工程(Kruskal)
    HDU 1879 继续畅通工程(Kruskra)
    HDU 1102 Constructing Roads(Kruskal)
    POJ 3150 Cellular Automaton(矩阵快速幂)
    POJ 3070 Fibonacci(矩阵快速幂)
    ZOJ 1648 Circuit Board(计算几何)
    ZOJ 3498 Javabeans
    ZOJ 3490 String Successor(模拟)
    Java实现 LeetCode 749 隔离病毒(DFS嵌套)
    Java实现 LeetCode 749 隔离病毒(DFS嵌套)
  • 原文地址:https://www.cnblogs.com/ISGuXing/p/8514209.html
Copyright © 2011-2022 走看看