题意:根据bij = si·sj把b矩阵想出来
1 2 3 4 5
2 4 6 8 10
3 6 9 12 15
4 8 12 16 20
5 10 15 20 25
例如子矩阵4 6 8
6 9 12
8 12 16 的和2*(2+3+4)+3*(2+3+4)+4*(2+3+4)=(2+3+4)*(2+3+4)
求有多少个子矩阵的和等于a;
思路:
例如矩阵(
bij,bxy
)用(si+s(i+1)+''''+sx)*(sj+s(j+1)+''''+sy)表示矩阵的值;
把所有子串和 和个数用数组存下来,因为字符串长度4000,每一个最多是9,所以总和最多是36000. int d【40000】,用d【i】表示子串和为 i 的有多少个,
若a是16,所以只有1*16,2*8,4*4可以。前两个不相等所以要*2(因为对称)。因为4==4所以不需要乘2。所以总个数是
d[1]*d[16]*2+d[2]*d[8]*2+d[4]*d[4];
难点;a==0这个地方真的很难处理,试了很长时间也没AC,参考了别人的博客才知道怎么处理0.0 看代码吧
m
ap换成数组也可以的。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
#include<string>
#define LL long long
using namespace std;
int a[4005];
map<int,LL>ma;
char p[4005];
int main()
{
int n;
scanf("%d",&n);
scanf("%s",p);
int lp=strlen(p);
for(int i=0;i<lp;i++)
a[i]=p[i]-'0';
int sum=0;
for(int i=0;i<lp;i++)
{
sum=0;
for(int j=i;j<lp;j++)
{
sum+=a[j];
ma[sum]++;
}
}
if(n==0)
{
LL ans1=0;
for(int i=1;i<50000;i++)
ans1+=ma[0]*ma[i]*2;
ans1+=ma[0]*ma[0];
printf("%I64d\n",ans1);
return 0;
}
LL ans=0;
int u=sqrt(n);
for(int i=1;i<=u;i++)
if(n%i==0)
ans+=ma[i]*ma[n/i];
ans*=2;
if(u*u==n)
ans-=ma[u]*ma[u];
printf("%I64d\n",ans);
return 0;
}
这题做了5.5小时才AC,是道好题。