HPU1288 矩阵翻硬币 【大数】

来源:互联网 发布:退火算法和遗传算法 编辑:程序博客网 时间:2024/05/17 07:43

1288: 矩阵翻硬币

时间限制: 10 Sec  内存限制: 128 MB
提交: 1  解决: 1
[提交][状态][讨论版] [Edit]

题目描述

问题描述  小明先把硬币摆成了一个 n 行 m 列的矩阵。   随后,小明对每一个硬币分别进行一次 Q 操作。   对第x行第y列的硬币进行 Q 操作的定义:将所有第 i*x 行,第 j*y 列的硬币进行翻转。   其中i和j为任意使操作可行的正整数,行号和列号都是从1开始。   当小明对所有硬币都进行了一次 Q 操作后,他发现了一个奇迹——所有硬币均为正面朝上。   小明想知道最开始有多少枚硬币是反面朝上的。于是,他向他的好朋友小M寻求帮助。   聪明的小M告诉小明,只需要对所有硬币再进行一次Q操作,即可恢复到最开始的状态。然而小明很懒,不愿意照做。于是小明希望你给出他更好的方法。帮他计算出答案。

输入

多组输入,每行两个正整数 n m,其中n、m <= 10^1000(10的1000次方),含义见题目描述。

输出

输出一个正整数,表示最开始有多少枚硬币是反面朝上的。

样例输入

2 3

样例输出

1

先考虑一维的情况,若第x个数被翻转奇数次,那么它的约数必定有奇数个,而只有平方数的约数是奇数个,那么也就是说对于一维的情况只有x为平方数时它才被翻转奇数次,对于二维的情况(x,y)点被翻转情况是x的约数*y的约数为该点翻转的次数,只有当这个数为奇数时,该点才被翻转奇数次,而奇数*奇数==奇数,也就是说x和y必须都是平方数才行,那么答案出来了,一个n行m列的矩阵在行上有sqrt(n)个平方数,在列上有sqrt(m)个平方数,组合出来的平方点对一共是sqrt(n)*sqrt(m).由于是大数,需要用字符串存储,大数相乘和大数开方直接用模板。

#include <iostream> #include <string>   using namespace std;   /* 大数相乘 */string operator * (string str1, string str2) {     string result = "";     int len1 = str1.length();     int len2 = str2.length();     int num[1002] = {0}; // 此处用来临时保存两数相乘的结果     int i, j;       if (!len1 || !len2) return "0"; // 处理空指针       for (i = 0; i < len1; ++i) {         for (j = 0; j < len2; ++j)             num[len1-1-i + len2-1-j] += (str1[i] - '0') * (str2[j] - '0');     }       for (i = 0; i < len1 + len2; ++i) {         num[i+1] += num[i] / 10;         num[i] %= 10;     }       for (i = len1 + len2 - 1; !num[i]; --i);     for ( ; i >= 0; --i)         result += num[i] + '0';           if (result.length() == 0) result = "0";     return result; }   bool str_bigger(string str1, string str2, int zeros) {     int len1 = str1.length();     int len2 = str2.length();     int i, j;       if (len1 + zeros < len2) return false;     else if (len1 + zeros > len2) return true;       for (i = 0; i < len1; ++i) {         if (str1[i] > str2[i]) return true;         else if (str1[i] < str2[i]) return false;     }       return false; }   /* 返回sqrt(n)的取整结果 */string sqrt_large(string str) {     int len = str.length();     int i, j, len1 = len >> 1;     string str1 = "";       if (len & 1) ++len1; // 长度为奇数,例如121=11*11           for (i = 0; i < len1; ++i) {         str1 += '0';         for (j = 0; j < 10; ++j) {             str1[i] = j + '0'; // attention             // 第三个参数为第一个串的尾零个数             if (str_bigger(str1 * str1, str, (len1-(i+1)) << 1)) {                 --str1[i]; break;             }         }     }       return str1; }   int main() {     // freopen("stdin.txt", "r", stdin);     // freopen("stdout.txt", "w", stdout);     string a, b;     while (cin >> a >> b) {         cout << sqrt_large(a) * sqrt_large(b) << endl;     }     return 0; } 


0 0
原创粉丝点击