問題描述小明先把硬幣擺成了一個 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 }