首页 > 代码库 > HPU1288 矩阵翻硬币 【大数】
HPU1288 矩阵翻硬币 【大数】
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; }
HPU1288 矩阵翻硬币 【大数】
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。