A*BBBB:原题链接

题意:

     给你两个值a和b,b的每一位都相同,求它们相乘后的结果。

注意:a和b的长度有1e6。

做题思路:

     很显然本题需要用到高精度,但普通高精度并不能解决本题,所以要针对本题做出优化。

     首先根据题意我们可以知道b的每一个值都是相同的,我们用个样例,看看可以得出什么。

样例假设:a=1234,b=111

     我们列出计算公式后,可以发现每一行的值都是相同的,在计算相加时,当前位置的值是该点原先的值加上它右侧的值,如,个位上为4,十位上为3+4=7,百位上为2+7=9,出于累加状态。

    1 2 3 4
  1 2 3 4
1 2 3 4
1 3 6 9 7 4

     很显然位置上的值不会一直出于累加状态,如千位上的值为1+2+3,将个位上的值4去除了,每个点上的值是怎么累加的呢,我们建个表直观感受一下。

累加和 状态
4 4
4,3 7
4,3,2 9
3,2,1 6

     有没有感觉到什么,是不是很像滑动窗口,当超出k时,就将超出k的部分弹出,而这个k值很明显就是b的长度,由此可以得到一条规则

//now为计数,当在超出b的长度后,此时i-lenb上的值已经超出,所以减去 
if (i>=lenb)now-=a[i-lenb]-'0';

     但这显然完成不了代码,我们继续模拟。

累加和 状态
3,2,1 6
2,1 3
1 1

     此时我们发现值一直在减少,原因很简单,它没东西可以加了嘛,当第一行的值加完时,now也同样不会继续累加。

    | 1 2 3 4
  1 | 2 3 4
1 2 | 3 4
1 3 | 6 9 7 4

     所以得出以下代码

//当在超出a的长度前,下一位值会处于累加状态 
if (i<lena)now+=a[i]-'0';

     接下来接可以使用经典的高精度解决问题了,可能有人问这只是当b相同值等于1的情况,要是不想同怎么办,那么ad+bd+cd是不是等于(a+b+c)*d,所以只要在高精度计算余数的部分乘以b[0]就可以了,并不会对题目造成影响。以下是AC代码。

#include <bits/stdc++.h>
using namespace std; 

const int N=1e7+10;
int t;
string a,b;

int main(){
	cin >>t;
	while(t--)
	{
		cin >>a>>b;
		//怎么来的让他怎么回去吧
		//数组存不下本题答案 
		string s="";
		//res记录每次按位计算时的值 
		int res=0;
		//因为b每一位都相同,所以直接拿出用来计算 
		int op=b[0]-'0';
		//拿出a,b的长度,便于计算 
		int lena=a.size();
		int lenb=b.size();
		//now为当前个位的值 
		int now=0;
		//因为是乘法计算,所以最终答案的长度会是两者相加减一 
		int maxn=lena+lenb;
		//因为从个位开始算起,所以将字符串倒叙 
		reverse(begin(a),end(a));
		for (int i=0;i<maxn;i++)
		{
			//当在超出a的长度前,下一位值会处于累加状态 
			if (i<lena)now+=a[i]-'0';
			//当在超出b的长度后,此时i-lenb上的值已经超出,所以减去 
			if (i>=lenb)now-=a[i-lenb]-'0';
			//计算该位置上的值 
			res+=now*op;
			//将他的余数放入s尾 
			s.push_back(res%10+'0');
			//并将余数除10,确保余数是个位数 
			res/=10;
		}
		//删除前导0 
		while(s.size()>1 && s.back()=='0')s.pop_back();
		//将s从逆序变正序 
		reverse(begin(s),end(s));
		cout <<s<<"\n";
	}
    return 0;
}