zoukankan      html  css  js  c++  java
  • Codeforces 364A

    原题地址:http://codeforces.com/problemset/problem/364/A

    题目大意:

    给定一个数字a(0 ≤ a ≤ 109)和一个数列s(每个数都是一位,长度不超过4000),定义一个矩阵Mij = si * sj ,求M有多少个子矩阵上面的数字和恰巧等于a

    算法分析:

    这道题是Codeforces Round #213 Div 1 Problem A && Div 2 Problem C,赛场上没写对,主要是没分析清楚,有一点想法就迫不及待地提交,结果白白提交了九次。后来以为自己想通了一个小BUG,转天又开始毛毛躁躁……看了数据才发现自己脑残忘了一种情况……教训十分沉重。

    首先我们定义一个子矩阵为(x, y, z, t),意思为以矩阵中的点(x, y)为左上角,(z, t)为右下角的子矩形。我们需要通过观察发现对于某个子矩形上的元素和,恰巧等于

    ( sumlimits_{i=x}^{z} s_{i} * sumlimits_{i=y}^{t} s_{i}) (这一点很容易证明)。接下来我们要做的就是预处理出来一个部分和( sum[i] = sumlimits_{x=1}^{i} s_{x} ),

    然后我们就可以用( n^2 )的时间求出s上任意一段的部分和。设w[t]为t在所有的部分和中出现的次数(亦即:枚举i和j(i ≤ j),若i到j的部分和为t,++w[t])

    那么,我们要求的就是对于a的每个因子q,( sumlimits_{q | a} w[q] * w[a / q] )。

    至于接下来……就是几个需要注意的我脑残的地方了

    1. s的最大长度为4000,每一位的最大值是9,所以w最大只需要到36000,保险起见开到40000。
    2. 尽管任何一段的部分和都不会超过36000,但是w[a/q]很可能使数组越界,需要特判
    3. 如果a=0,需要进行特殊处理
     1 //date 20131119
     2 #include <cstdio>
     3 #include <string>
     4 #include <iostream>
     5 #include <cstring>
     6 
     7 using namespace std;
     8 
     9 const int maxn = 4050;
    10 const int maxa = 50000;
    11 
    12 long long a, ans;
    13 string s;
    14 int sum[maxn];
    15 int w1[maxa];
    16 
    17 int main()
    18 {
    19     //freopen("matrix.in", "r", stdin);
    20     //freopen("matrix.out", "w", stdout);
    21     cin >> a;
    22     ans = 0;
    23     
    24     //if(a == 0L){printf("0
    "); return 0;}
    25     
    26     cin >> s;
    27     int l = s.length();
    28     for(int i = 1; i <= l; ++i) sum[i] = s[i - 1] - '0';
    29     for(int i = 1; i <= l; ++i)
    30         sum[i] = sum[i - 1] + sum[i];
    31 
    32     for(int i = 1; i <= l; ++i)
    33         for(int j = 1; j <= i; ++j)
    34             w1[sum[i] - sum[j - 1]]++;
    35         
    36     
    37     if(a > 0)
    38         for(int i = 1; i < maxa; ++i)
    39         {
    40             if(a % (long long)i == 0)
    41             {
    42                 if((a / (long long)i) >= maxa)continue;
    43                 ans += (long long)w1[i] * (long long)w1[a / (long long)i];
    44             }
    45         }
    46     
    47     else{
    48         for(int i = 1; i < maxa; ++i)
    49             ans += (long long)w1[0] * (long long)w1[i];
    50         ans *= 2L; ans += (long long)w1[0] * (long long)w1[0];
    51     }
    52     cout << ans << endl;
    53     return 0;
    54 }    

     继续加油!

  • 相关阅读:
    Java实现 LeetCode 792 自定义字符串排序(暴力)
    Java实现 LeetCode 792 自定义字符串排序(暴力)
    asp.net session对象的持久化
    Java实现 LeetCode 791 自定义字符串排序(桶排序)
    Java实现 LeetCode 791 自定义字符串排序(桶排序)
    Java实现 LeetCode 791 自定义字符串排序(桶排序)
    Java实现 LeetCode 790 多米诺和托米诺平铺(递推)
    Java实现 LeetCode 790 多米诺和托米诺平铺(递推)
    Java实现 LeetCode 790 多米诺和托米诺平铺(递推)
    小白也能看懂的约瑟夫环问题
  • 原文地址:https://www.cnblogs.com/w007878/p/3434561.html
Copyright © 2011-2022 走看看