You have a string of decimal digits s. Let's define bij = si·sj. Find in matrix b the number of such rectangles that the sum bij for all cells(i, j) that are the elements of the rectangle equals a in each rectangle.
A rectangle in a matrix is a group of four integers (x, y, z, t) (x ≤ y, z ≤ t). The elements of the rectangle are all cells (i, j) such that x ≤ i ≤ y, z ≤ j ≤ t.
The first line contains integer a (0 ≤ a ≤ 109), the second line contains a string of decimal integers s (1 ≤ |s| ≤ 4000).
Print a single integer — the answer to a problem.
Please, do not write the %lld specifier to read or write 64-bit integers in С++. It is preferred to use the cin, cout streams or the %I64dspecifier.
解题:
1) 明确目标,本题的目标是需要求得矩阵中矩形内元素之和等于a的矩形数量。
2) 矩形的形成,两行两竖即可生成。即下图所示:
3) 得到矩形内的元素之和,所有元素为 b(ac) …… b(ad); b(a+1 c)…… b(a+1 d); …… ; b(b c)……b(b d);
由于b(ij) = si.sj ; 所以求得矩形内所有元素之和为S= [s(a) +s(a+1)……s(b)] [ s(c) + s(c+1)……s(d)] ,可以看出S为两个连续字串之和的乘积;
设字符串为s,要求得S=a的个数,首先要求得连续字串之和,其次找到所有的和中满足乘积等于a的个数
4) 求解连续字串之和算法
k(c,d) = s(d) - s(c) ,其中s(d)表示前d个字符数字之和,k(c,d)表示[c,d]之间子串数字之和,即为所求;
而s(d) 可以表示为s(d-1)+s[d]-‘0’,通过递推可以得到每一个s(i)的值, 假设从1开始编号;
5) 通过求得所有连续字串之和,下一步可以得到任意间隔之和集合P(允许重复),然后求得该集合内两数乘积等于a的数的个数;
6)了解该集合的特征: 0<= p <= s(n)<=50000;采用标记是否存在的方法来验证改元素,用t[50001] 来记录任意间断之和的数量;
7) 计算,特例 a = 0; 则至少一个k(c,d)=0;则 ans = t[0]*t[0] + 2*sum*t[0] ,计算为,两个都为0,或者只有一个为0;其中sum为除t[0]外集合P(允许重复)数量;
8) 计算乘积等于a,
1. 记录每个数出现的次数 t[i] 表示
2. 判断如何a%i==0;记忆a/i<=s(n),则肯定集合中存在两个数相乘等于a,数量为 ans+= t[i] * t[a/i]
很显然,这里要提前排除i=0的情况,因此需要先判断a?0,如果是,则先计算 ans+= t[0] * t[i](0<= i<= n)
9) 注意事项,由于s(n)<=50000,即由于codefirst中int 为16位有符号整数,表示的范围为:-32768 ~ 32767,导致如果用int s[50000] 将会导致溢出,因此需要用long(32) 或者 long long(64) 来表示。由于溢出,第12个例子一直没能够跑出来,这个需要注意。
#include <iostream> #include <string> using namespace std; long long s1[4001]; long long t1[50000]; int main() { long long a; cin>>a; string s; cin>>s; int len = s.length(); long long i,j; for(i=0;i<len;i++){ s1[i+1] = s1[i]+s[i]-'0'; // the continuous distance problem // t1[s1[i+1]]++; } for(i=1;i<=len;i++) { for(j=0;j<i;j++){ t1[s1[i]-s1[j]]++; // exist problem s1[n] >= s1[j]-s1[i] >= 0 } } long long ans=0; if(a==0) { for(i=0;i<=s1[len];i++) ans+=t1[0]*t1[i]; // the multiply result is zero } for(i=1;i<=s1[len];i++) if((a%i==0)&&(a/i<=s1[len])) ans+=t1[i]*t1[a/i]; cout<<ans<<endl; return 0; }