[20200721NOIP提高组模拟T1]矩阵

题目大意:

 给你一个数A,以及一串全是数字的字符串以构造矩阵C,C[i][j]=a[i]*a[j](a[k]表示字符串中第k位所代表的数字).请你求出权值之和恰好为A的子矩阵个数.

solution:

 此题比较有意思.题目要我们求的答案即满足$(sum_{i=x}^{u}sum_{j=y}^{v} C[i][j]) ==A$的四元组[x,y,u,v]个数.接下来我们分析一下这个式子:$$sum_{i=x}^{u}sum_{j=y}^{v}C[i][j]=sum_{i=x}^{u}sum_{j=y}^{v} a[i] cdot a[j]=sum_{i=1}^{u}(a[i] cdot sum_{j=y}^{v}a[j])=sum_{i=x}^{u}a[i] cdot sum_{j=y}^{v}a[j]$$$$=(sum[u]-sum[x-1]) cdot (sum[v]-sum[y-1])$$其中sum[]数组为前缀和.由于n比较小$(nin 4000)$,所以我们可以n²预处理出前缀和之差,然后运用乘法原理组合即可.值得注意的是,当A==0时,由于0乘以任何数结果均为0,所以要特殊处理,0*0的矩阵被我们算了两次,所以要减掉一次.

code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#define R register
#define next exnttttttttttttttttttttt
#define debug puts("mlg")
using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
inline ll read();
inline void write(ll x);
inline void writesp(ll x);
inline void writeln(ll x);
ll A;
char wn;
ll num[6000],n;
ll used[150000],sum[150000];
ll ans;
int main(){
    A=read();
    wn=getchar();
    while(wn<'0'||wn>'9') wn=getchar();
    while(wn>='0'&&wn<='9'){
        num[++n]=wn-'0';wn=getchar();
    } 
    for(R ll i=1;i<=n;i++){
        sum[i]=sum[i-1]+num[i];
    }
    for(R ll i=1;i<=n;i++){
        for(R ll j=1;j<=i;j++){
            ++used[sum[i]-sum[j-1]];
        }
    }
    if(A==0){
        for(R ll i=0;i<=120000;i++) ans+=used[0]*used[i];
        ans<<=1;ans-=used[0]*used[0];
        writeln(ans);return 0;
    }
    for(R ll i=1;i<=120000;i++){
        if(A%i==0&&used[i]&&i*100000>=A){
            ans+=used[i]*used[A/i];
        }
    }
    writeln(ans);
}
inline ll read(){
    ll x=0,t=1;char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-') t=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*t;
}
inline void write(ll x){
    if(x<0){putchar('-');x=-x;}
    if(x<=9){putchar(x+'0');return;}
    write(x/10);putchar(x%10+'0');
}
inline void writesp(ll x){
    write(x);putchar(' ');
}
inline void writeln(ll x){
    write(x);putchar('
');
}

 

 

原文地址:https://www.cnblogs.com/ylwtsq/p/13356111.html