题目大意:给一串数字串和一个数a,b(ij) = s(i) * s(j),,求矩阵b中存在多少个矩形使矩形里的数的和等于a.
做法:每一个矩阵都有x的限制范围和y的限制范围,假设分别为x1,x2,y1,y2.即,在矩阵中所有的点的横坐标必定在(x1,x2)中,纵坐标必定在(y1,y2)中,所以第x1行的数的和为
s(x1)*s(y1)) + (s(x1) * s(y1+1)) + (s(x1)*s(y1+2))+.....+(s(x1)*s(y2) = s(x1) * (s(y1) + s(y1+1) + s(y1+2)+.....+s(y2)),则第x1+1行的数的和就为s(x2) *(s(y1) + s(y1+1)
+s(y1+2)+.....+s(y2)), 所以所有数的和为(s(x1) + s(x1+1)+....s(x2)) * (s(y1) + s(y1+1)+.....+s(y2) );所有就求a的约数,然后将所有no[i]*no[(a/i)]相加。
要单独考虑一下a为0的情况,当a为0时,就说明相乘的两边至少有一边为0, 但是会有重复的情况,所以当左边为0时,考虑一下右边不为0的情况,当右边为0,左边不为
0的情况是一样的,然后再考虑一下都为0的情况。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <map>
#define M 10000
using namespace std;
map<int , int> mp;
long long di[M], sum[4500], cont, no[M], num[4500], len;
int a;
void solve(int a){
cont = 0;
for(int i = 1; i <= sqrt(a); i++){
if(a%i == 0)
{
di[++cont] = i;
if(i * i != a)
di[++cont] = a / i;
}
}
for(int i = 1; i <= cont; i++){
mp[di[i]] = i;
}
}
int main(){
int i, j;
char s[4500];
while(scanf("%d", &a) != EOF){
getchar();
scanf("%s", s);
memset(no, 0, sizeof(no));
mp.clear();
len = strlen(s);
for(i = 0; i < len; i++)
num[i+1] = s[i]-'0';
sum[0] = 0;
for(i = 1; i <= len; i++)
sum[i] = sum[i-1] + num[i];
long long temp = 0;
if(a == 0){
for(i = 1; i <= len; i++)
for(j = 1; j <= i; j++)
if(sum[i] - sum[j-1] == 0)
temp++;
int pp = (len+1)*len/2;
//左边为0,右边不为0的情况为(pp-temp)* temp种,
//两边都为0 的情况为temp*temp
printf("%I64d\n", (long long)(pp-temp)*temp*2+temp*temp);
continue;
}
solve(a);
int diff;
for(i = 1; i <= len; i++){
for(j = 1; j <= i; j++){
diff = sum[i] - sum[j-1];
if(mp[diff]) no[mp[diff]] ++;
}
}
long long ans = 0;
for(i = 1; i <= cont; i++){
ans += no[mp[di[i]]] * no[mp[a/di[i]]];
}
printf("%I64d\n", ans);
}
return 0;
}