藍橋杯-矩陣翻硬幣

weixin_34104341發表於2020-04-07
問題描述
  小明先把硬幣擺成了一個 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 }

 

 

轉載於:https://www.cnblogs.com/ISGuXing/p/8514209.html