AcWing 1230. K倍区间 解题思路及题解

先贴个题目:

以及原题链接: 1230. K倍区间 - AcWing题库icon-default.png?t=N7T8https://www.acwing.com/problem/content/1232/

讲讲思路,这题其实可以暴力如果数据不够强的话,但很显然以acwing的数据是不行的,因为暴力差不多就是n方复杂度,1e10的计算量只会收获TLE,所以考虑优化。这里我们可以自己找规律也可以利用裴蜀定理(详见裴蜀定理_百度百科 (baidu.com))。这里简单概括,如果(a-b)%k=0,那么a%k=b%k。接下来就可以搞定一个O(n)的算法了。

#include <iostream>
using namespace std;
int main()
{
    int n, k ;
    long long sum = 0;
    cin >> n >> k;
    long long *a = new long long[n + 10];
    long *b = new long[n + 10];
    cin >> a[1];
    for (int i = 2; i < n + 1; ++i){
        int num;
        cin >> num;
        a[i] = a[i - 1] + num;
    }
    b[0] = 1;
    for (int i = 1; i < n + 1; ++i){
        sum += b[a[i] % k];
        b[a[i] % k]++;
    }
    cout << sum;
}

a数组用来存前缀和,b数组用来存到当前位置时每种a%k的余数的节点已经有几个,然后遍历,每次遇到就加上可能的节点选取(即节点数),然后让节点数加一,最后输出总和就好。

这里需要注意:因为本身如果可以被除尽,那么自身也是一个k倍区间,所以要把b[0]设为1.

b[0] = 1;

(昨晚太晚了今早起来写题解)

by————2024.2.3刷题记录

  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值