您的位置:首页 > 其它

蓝桥杯 历届试题 矩阵翻硬币

2016-02-18 16:34 381 查看
很夸张的题目

我从头到尾题目意思都理解错了

没错 这句话暴露出我看了题解

这道题就是个大数开根号 因为第x行只能被x的约数xi影响 本来最后是正面朝上的 现在需要反面(逆推回去)

就必须要翻奇数次

也就是求一个数 奇数X=xi*yi (xi和yi分别表示某个数的约数) 然后符合这样的数有什么条件

首先 xi yi 也都必须是奇数 别给我说其中一个是偶数还会满足条件

然后 困难来了 什么数的约数会有奇数个

不知道就先打表play

1. 1
2. 2
3. 2
4. 3
5. 2
6. 4
7. 2
8. 4
9. 3
10. 4
11. 2
12. 6
13. 2
14. 4
15. 4
16. 5


大家可以找一找 有奇数个 约数的数有什么共同特征?

1 4 9 16

当然 你也可以继续写下去 会发现 这是个完全平方数

根据数据 这道题就是个大数开方题了

大数怎么开方?

根据一个牛顿b进定理(不知道名字是不是对的……)

奇数开方的结果是(n>>1 |1) 位,而偶数的结果是(n>>1) 位

证明去问牛顿

#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())
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;
}

string sqrt_(string str) {
int len = str.length();
int i, j, len1 = len >> 1;
string str1 = "";
///假如一个数有偶数位n,那么这个数的方根有n/2位;如果n为奇数,那么方根为(n+1)/2位
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';
/// 第三个参数为第一个串的尾零个数
if (str_bigger(str1 * str1, str, (len1-(i+1)) << 1)){
--str1[i]; break;
}
}
}
return str1;
}

int main(){
string a, b;
while (cin >> a >> b){
cout << sqrt_(a) * sqrt_(b) << endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: