[前缀和] Jzoj P4259 矩形
题解
- 我们发现b[i][j]=s[i]*s[j]
- 那么考虑一下如果i或j相等是,行或列会有共同的公因数
- 可以得到a=sum[x1...x2]*sum[y1...y2]
- 那么sum[x1...x2]和sum[y1...y2]都是a的倍数
- 考虑枚举sum[x1...x2]的值
- 可以用前缀和,用num[i]记录出现i的次数
- 那么就可以枚举sum[x1...x2]
- 那么对于答案的贡献就是num[a/sum[x1...x2]]*num[sum[x1...x2]]
- 你以为就这样就可以A了吗。。。。。
- 考虑一下a为0时
- sum[y1...y2]可以取任意值
代码
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<cstring> 5 using namespace std; 6 long long x,ans,len,a[40010],num[40010],k; 7 char s[40100]; 8 int main() 9 { 10 scanf("%lld",&x); scanf("%s",s+1); 11 len=strlen(s+1); 12 for (int i=1;i<=len;i++) a[i]=a[i-1]+s[i]-'0'; 13 for (int i=1;i<=len;i++) 14 for (int j=i;j<=len;j++) 15 num[a[j]-a[i-1]]++; 16 if (x!=0) 17 { 18 for (int i=1;i<=len;i++) 19 for (int j=i;j<=len;j++) 20 { 21 k=a[j]-a[i-1]; 22 if (!k) continue; 23 if (x%k!=0) continue; 24 if (x/k>36000) continue; 25 ans+=num[x/k]; 26 } 27 } 28 else 29 { 30 for (int i=1;i<=len;i++) 31 for (int j=i;j<=len;j++) 32 { 33 k=a[j]-a[i-1]; 34 if (k==0) ans+=len*(len+1)/2; else ans+=num[0]; 35 } 36 } 37 printf("%lld",ans); 38 return 0; 39 }