题目大意
给定一个由数字(0-9)构成的字符串s。我们可以由此定义出size(s) * size(s) 大
小的矩阵b,其中b[i][j] = s[i] * s[j];请问在这个矩阵b中,有多少子矩形满足其中的b[i][j]的和为另一个给定的数字a。
水题
预处理前缀和,然后变成了某因数个数个数统计问题,太水了我讲的不详细也没事。
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
ll i,j,k,l,t,n,m;
ll ans;
ll s[5000],sum[5000];
ll ha[200000+10],cnt[200000+10];
char ch;
ll read(){
ll x=0;
char ch=getchar();
while (ch<'0'||ch>'9') ch=getchar();
x=ch-'0';
return x;
}
ll hash(ll x){
ll k=(x-1)%200000+1;
while (ha[k]!=0&&ha[k]!=x) k=k%200000+1;
return k;
}
int main(){
//freopen("t1.in","r",stdin);freopen("t1.out","w",stdout);
scanf("%lld",&n);
s[1]=read();
m=1;
while (1){
ch=getchar();
if (ch<'0'||ch>'9') break;
s[++m]=ch-'0';
}
fo(i,1,m) sum[i]=sum[i-1]+s[i];
fo(i,1,floor(sqrt(n)))
if (n%i==0){
k=hash(i);
ha[k]=i;
k=hash(n/i);
ha[k]=i;
}
if (!n){
fo(i,1,m)
fo(j,i,m){
t=sum[j]-sum[i-1];
if (!t) ans++;
}
ans=ans*((m+1)*m/2)*2-ans*ans;
printf("%lld\n",ans);
//fclose(stdin);fclose(stdout);
return 0;
}
fo(i,1,m)
fo(j,i,m){
t=sum[j]-sum[i-1];
if (t&&n%t==0) cnt[hash(t)]++;
}
fo(i,1,m)
fo(j,i,m){
t=sum[j]-sum[i-1];
if (t&&n%t==0) ans+=cnt[hash(n/t)];
}
printf("%lld\n",ans);
//fclose(stdin);fclose(stdout);
}