codeforces364A--- Matrix

点击打开链接

题目大意:给一串数字串和一个数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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值