歷屆試題 矩陣翻硬幣
時間限制:1.0s 記憶體限制:256.0MB
問題描述
小明先把硬幣擺成了一個 n 行 m 列的矩陣。
隨後,小明對每一個硬幣分別進行一次 Q 操作。
對第x行第y列的硬幣進行 Q 操作的定義:將所有第 i*x 行,第 j*y 列的硬幣進行翻轉。
其中i和j為任意使操作可行的正整數,行號和列號都是從1開始。
當小明對所有硬幣都進行了一次 Q 操作後,他發現了一個奇蹟——所有硬幣均為正面朝上。
小明想知道最開始有多少枚硬幣是反面朝上的。於是,他向他的好朋友小M尋求幫助。
聰明的小M告訴小明,只需要對所有硬幣再進行一次Q操作,即可恢復到最開始的狀態。然而小明很懶,不願意照做。於是小明希望你給出他更好的方法。幫他計算出答案。
隨後,小明對每一個硬幣分別進行一次 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次方)。
對於20%的資料,n、m <= 10^7;
對於40%的資料,n、m <= 10^15;
對於10%的資料,n、m <= 10^1000(10的1000次方)。
最近狀態沒調好。。。。休息一下。
1 #include<iostream> 2 #include<string> 3 #include<stdio.h> 4 using namespace std; 5 6 //兩個字串相乘 7 string strMultiply(string str1 , string str2) 8 { 9 string strResult = ""; 10 int len1 = str1.length(); 11 int len2 = str2.length(); 12 int num[500] = {0}; 13 int i = 0, j = 0; 14 for(i = 0; i < len1; i++) 15 { 16 for(j = 0; j < len2; j++) 17 { 18 num[len1-1 - i + len2-1 - j] += (str1[i] - '0')*(str2[j] - '0'); 19 // printf("num[%d]=%d=%c*%c\n",(len1-1 - i + len2-1 - j),num[len1-1 - i + len2-1 - j],str1[i],str2[j]); 20 21 } 22 } 23 // puts(""); 24 for(i = 0; i < len1 + len2; i++) 25 { 26 num[i+1] += num[i] / 10; 27 28 num[i] = num[i] % 10; 29 // printf("%d ",num[i]); 30 } 31 32 for(i = len1 + len2 - 1; i >= 0 ; i--) 33 { 34 if(0 != num[i]) break; 35 } 36 37 for(j = i; j >= 0; j--) 38 { 39 strResult += num[j] + '0'; 40 } 41 return strResult; 42 } 43 44 //str1 * 10^pos後(即在str1後添上pos個0),與str2作比較 45 int compare(string str1, string str2, int pos) 46 { 47 int len1 = str1.length(); 48 int len2 = str2.length(); 49 if(len2 > len1+pos) return 0; 50 if(len2 < len1+pos) return 1; 51 int i = 0; 52 for(i = 0; i < len2; i++) 53 { 54 if(str1[i]-'0' > str2[i]-'0') return 1; 55 if(str1[i]-'0' < str2[i]-'0') return 0; 56 } 57 return 0; 58 } 59 60 //對大數str開方取整 61 string sqrtLarge(string str) 62 { 63 int len = str.length(); 64 int i = 0; 65 int j = 0; 66 string strResult = ""; 67 string str1 = ""; 68 if(0 == len % 2) 69 { //為偶數位 70 for(i = 0; i < len/2; i++) 71 { 72 for(j = 0; j < 10; j++) 73 { 74 str1 = strResult; 75 str1 += j + '0'; 76 if(1 == compare(strMultiply(str1, str1) , str , 2*(len/2-i-1)) ) 77 { //由於str1後少了len/2-i-1個0,所以平方以後少了2*(len/2-i-1)個 78 strResult += j-1 + '0'; 79 break; 80 } 81 if(9 == j) strResult += '9'; 82 } 83 } 84 } 85 else 86 { //為奇數位 87 for(i = 0; i < len/2+1; i++) 88 { 89 for(j = 0; j < 10; j++) 90 { 91 str1 = strResult; 92 str1 += j + '0'; 93 if(1 == compare(strMultiply(str1, str1) , str , 2*(len/2-i)) ) 94 { 95 strResult += j-1 + '0'; 96 break; 97 } 98 if(9 == j) strResult += '9'; 99 } 100 } 101 } 102 return strResult; 103 } 104 int main() 105 { 106 string str1; 107 string str2; 108 string strResult; 109 cin>>str1>>str2; 110 111 cout<<strMultiply(sqrtLarge(str1) , sqrtLarge(str2))<<endl; 112 113 return 0; 114 }