2020.7.21 T1矩阵(jz暑假训练day6)

Description

给定一个由数字(0-9)构成的字符串s。我们可以由此定义出size(s) * size(s) 大
小的矩阵b,其中b[i][j] = s[i] * s[j];请问在这个矩阵b中,有多少子矩形满足其中的b[i][j]的和为另一个给定的数字a。

Input

第一行一个整数a。
第二行字符串s。

Output

一个整数表示满足条件的子矩形数。

Sample Input

10
12345

Sample Output

6

【样例解释】

b 矩阵为:
01 02 03 04 05
02 04 06 08 10
03 06 09 12 15
04 08 12 16 20
05 10 15 20 25
和为 10 的子矩形有:
一、01 02 03 04
二、
01
02
03
04
三、04 06
四、
04
06
五、10
六、10
以上共六个。

Data Constraint

对 10%的输入数据:size(s)≤10
对30%的输入数据:size(s)≤100
对100%的输入数据:0 ≤a≤1000000000,size(s)≤4000

赛时

思想ac,然后oj运行坑人,之后数组太小,0没特判等等。。。。。。0分

正解

都说思想ac了,对于每个矩阵从i,j(左上角)到x,y(右下角),它的值其实就是(s[x]-s[i-1])*(s[y]-s[j-1]),s为前缀和。那么如果一个矩阵的答案是a的话,(s[x]-s[i-1])与(s[y]-s[j-1])都应该是a的约数,于是我们用个桶装一下可能的s值的个数,然后就找a的两个约数,当这两个约数不一样时,ans就加上这两个约数的个数的乘积再乘2,如果一样的话,就不乘2。最后a=0时需特判,答案就是s值为0时,其他数可以任意取,也就是bz[0](0的数量) *其他数的数量,而其他数的数量其实是(len+1)*len/2也就是等差数列。最后还要减去bz[0]*bz[0],至于为什么,其实同理上面约数相等时要不用乘2,那么这里也就是减去多的。

代码

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
using namespace std;
int a,cnt,s[40007],ans,bz[10000000];
int main(){
	scanf("%d",&a);
	char ch=getchar();
	while(ch<'0'||ch>'9') ch=getchar();
	while(ch>='0'&&ch<='9'){
		s[++cnt]=ch-'0';
		ch=getchar();
	}
	for(int i=1;i<=cnt;i++)
		s[i]+=s[i-1];
	for(int i=1;i<=cnt;i++)
		for(int j=i;j<=cnt;j++)
			bz[s[j]-s[i-1]]++;
	for(int i=2;i<=trunc(sqrt(a));i++)
		if(a%i==0)
			if(bz[i]&&bz[a/i]){
				if(i!=a/i) ans+=bz[i]*bz[a/i]*2;
				else ans+=bz[i]*bz[a/i];
			}
	if(a==0){
		for(int i=1;i<=s[cnt];i++)
			ans+=bz[i];
		ans*=bz[0]*2;
		ans+=bz[0]*bz[0];
	}
	printf("%d\n",ans);
}

猜你喜欢

转载自blog.csdn.net/jay_zai/article/details/107499628
今日推荐