序列卷积之和

链接:https://ac.nowcoder.com/acm/contest/5633/C
解法1:这题看到一个不停使用前缀和优化最后达成O(n)计算的方法,感觉很有趣
他的分析过程是这样:
首先暴力4重循环

for(int l=1; l<=n; l++){
    for(int r=l; r<=n; r++){
        for(int i=l; i<=r; i++){
            for(int j=i; j<=r; j++){
                ans += a[i]*a[j];
            }
        }
    }
}

令b[i]=a[1]+a[2]+...+a[i]
减掉一层循环

for(int l=1; l<=n; l++){
    for(int r=l; r<=n; r++){
        for(int i=l; i<=r; i++){
            ans+=a[i]*(b[r]-b[i-1]);
        }
    }
}

再令d[i]=a[i]*b[i-1]
c[i]=d[1]+d[2]+...+d[i]
再去掉一层循环

for(int l=1; l<=n; l++){
    for(int r=l; r<=n; r++){
        ans += b[r]*(b[r]-b[l-1]) - (c[r]-c[l-1]);
    }
}

再把式子展开,发现预处理bb的前缀和,b的前缀和,c的前缀和即可O(n)实现计算。
解法2:
这种题要立刻想到打表找规律。
图片说明
i j:a[i]a[j]出现的次数
前缀和预处理a[j],
s[i] = a[1]
n+a[2]
(n-1)+...+a[i](n-i+1)的话
答案就是a[i]
(s[n]-s[i-1])*i
代码:

#include <bits/stdc++.h>
using namespace std;
#define IO ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
#define debug(x) cout << #x << ": " << x << endl;
#define all(__vv__) (__vv__).begin(), (__vv__).end()
#define endl "\n"
#define SZ(x) ((int)(x).size())
#define pb push_back
#define pii pair<int, int>
#define mem(__x__,__val__) memset(__x__, __val__, sizeof(__x__))
typedef long long ll; typedef unsigned long long ull; typedef long double ld;
inline ll read() { ll s = 0, w = 1; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch == '-') w = -1; for (; isdigit(ch); ch = getchar())    s = (s << 1) + (s << 3) + (ch ^ 48); return s * w; }
inline void print(ll x, int op = 10) { if (!x) { putchar('0'); if (op)    putchar(op); return; }    char F[40]; ll tmp = x > 0 ? x : -x;    if (x < 0)putchar('-');    int cnt = 0;    while (tmp > 0) { F[cnt++] = tmp % 10 + '0';        tmp /= 10; }    while (cnt > 0)putchar(F[--cnt]);    if (op)    putchar(op); }
inline ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; }
ll qpow(ll a, ll b) { ll ans = 1;    while (b) { if (b & 1)    ans *= a;        b >>= 1;        a *= a; }    return ans; }    ll qpow(ll a, ll b, ll mod) { ll ans = 1; while (b) { if (b & 1)(ans *= a) %= mod; b >>= 1; (a *= a) %= mod; }return ans % mod; }
const int dir[][2] = { {0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1} };
const int MOD = 1e9+7;
const int INF = 0x3f3f3f3f;
const int N = 2e5+10;

int n;
ll a[N], s[N];
int main()
{
    n = read();
    for(int i=1; i<=n; i++){
        a[i] = read(); s[i] = (s[i-1] + a[i] * (n-i+1) % MOD) % MOD;
    }
    ll ans = 0;
    for(int i=1; i<=n; i++){
        ans = (ans + a[i] * ((s[n]-s[i-1]+MOD)%MOD) % MOD * i % MOD) % MOD;
    }
    print(ans);
}
全部评论

相关推荐

点赞 评论 收藏
分享
来,说点可能被同行“骂”的大实话。🙊当初接数字马力Offer时,朋友都说:“蚂蚁的“内包”公司?你想清楚啊!”但入职快一年后的今天,我反而对他有了不一样的看法!🔹&nbsp;是偏见?还是信息差!之前没入职之前外面都在说什么岗位低人一等这类。实际上:这种情况不可至否,不能保证每个团队都是其乐融融。但我在的部门以及我了解的周边同事都还是十分好相处的~和蚂蚁师兄师姐之间也经常开一些小玩笑。总之:身份是蚂蚁公司给的,地位是自己挣的(一个傲娇女孩的自述)。🔹&nbsp;待遇?玩的就是真实!试用期工资全额发!六点下班跑得快(早9晚6或者早10晚7,动态打卡),公积金顶格交。别听那些画饼的,到手的钱和下班的时间才是真的(都是牛马何必难为牛马)。🔹&nbsp;能不能学到技术?来了就“后悔”!我们拥有权限直通蚂蚁知识库,技术栈多到学不完。说“学不到东西”的人,来了可能后悔——后悔来晚了(哈哈哈哈,可以不学但是不能没有)!💥&nbsp;内推地址:https://app.mokahr.com/su/ueoyhg❗我的内推码:NTA6Nvs走我的内推,可以直达业务部门,面试流程更快速,进度可查!今天新放HC,之前挂过也能再战!秋招已经正式开始啦~机会就摆在这,敢不敢来试一试呢?(和我一样,做个勇敢的女孩)
下午吃泡馍:数字马力的薪资一般哇,5年经验的java/测试就给人一万出头,而且刚入职第三天就让人出差,而且是出半年
帮你内推|数字马力 校招
点赞 评论 收藏
分享
评论
3
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务