蓝桥杯 矩阵翻硬币

蓝桥杯 矩阵翻硬币

暴力

  • 暴力模拟: 但是发现暴力模拟只能通过第一个样例,因为数的范围太大了,所以说是思路上的问题

考虑整个过程

我参考了h_hui_hui大佬的博客,他写的很详细,很容易看懂

感觉那样一步一步推导出结果的过程很酷,也很难

现在能看懂,但是如果自己想的话就可能出问题,积累经验吧

具体分析请看博客

结论

ans = sqrt(n) * sqrt(m) # 两个都是向下取整

所以会用到大数相乘, 大数开根号

还有一个结论:

假设位数为len的整数,开方取整后为一个lenSqrt位数

当len为偶数,lenSqrt = len / 2
当len为奇数,lenSqrt = (len / 2) + 1

其中大数相加可以通过我的上一篇博客了解

比较佩服大佬的一点就是开根号那个操作,实在是厉害

code

#include <bits/stdc++.h>

//find a solution : cnt = sqrt(m) * sqrt(n) and ji * ji = ji
//大数相乘,大数开根号
 
using namespace std;

string strMultiply(string str1,string str2){
	string strResult = "";
	int len1 = str1.length();
	int len2 = str2.length();
	int num[500] = {0};
	int i = 0 , j = 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');//这里当时写错了不是两个 i str1[i] str2[j] 
		}
	}
	for(i = 0 ; i < len1+len2; i++){
		if(num[i] >= 10){
			num[i+1] += num[i]/10;
			num[i] %= 10; 
		}
	}
	for(i = len1+len2-1; i>= 0; i--){
		if(num[i] != 0)break;	
	}
	
	for(j = i ; j >= 0; j--){
		strResult += num[j] + '0';
	}
	return strResult;	
} 

//添加 pos 个 0 然后在做比较 
int compare(string str1,string str2,int pos){
	int len1 = str1.length();
	int len2 = str2.length();
	if(len2 > len1 + pos)return 0;
	if(len2 < len1 + pos)return 1;
	int i = 0;
	for(i = 0; i < len2; i++){
		if(str1[i]-'0'>str2[i]-'0')return 1;
		if(str1[i]-'0'<str2[i]-'0')return 0;
	}
	return 0;
}
// 如果数比较大的话,可能会出现不该出现的 比如 : /
 
string sqrtLarge(string str){
	int len = str.length();
	int i = 0, j = 0;
	string strResult = "";
	string str1 = "";
	
	if(0 == len % 2)  
    {         //为偶数位  
        for(i = 0; i < len/2; i++)
        {  
            for(j = 0; j < 10; j++)  
            {  
                str1 = strResult;  
                str1 += j + '0';  
                if(1 == compare(strMultiply(str1, str1) , str , 2*(len/2-i-1)) )  
                {         //由于str1后少了len/2-i-1个0,所以平方以后少了2*(len/2-i-1)个  
                    strResult +=  j-1 + '0';
                    break;  
                }  
                if(9 == j) strResult += '9';  
            }  
        }  
    }
    else  
    {       //为奇数位  
        for(i = 0; i < len/2+1; i++)  
        {  
            for(j = 0; j < 10; j++)  
            {  
                str1 = strResult;  
                str1 += j + '0';  
                if(1 == compare(strMultiply(str1, str1) , str , 2*(len/2-i)) )  
                {  
                    strResult +=  j-1 + '0';
                    break;  
                }  
                if(9 == j) strResult += '9';  
            }  
        }  
    }  
    return strResult;  
}

int main(){
	string str1;
	string str2;
//	string strResult;
	cin >> str1 >> str2;
	cout << strMultiply(sqrtLarge(str1),sqrtLarge(str2)) << endl;
		
	return 0;
} 
//test
//979 938
//930

总结

如果是自己的话,推导,实现,这两个都成问题,
特别是开根号那个操作,看了很长时间,加油吧,累计做题经验吧
原文地址:https://www.cnblogs.com/pprp/p/8666324.html