nowCoder:再编号(数列找规律)

本文解析了nowcoder题目的再编号问题,介绍了一种通过奇偶讨论和等比数列规律求解每次编码后编号的方法。关键在于理解编号的更新规则和利用模运算技巧。适合后端开发者和算法竞赛爱好者阅读。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

nowCoder 再编号

nnn个人,每个人有一个编号aia_iai
定义对 aaa 的再编号为 a′a'a ,满足ai′=(∑j=1naj)−aia_i'=(\sum_{j=1}^na_j) - a_iai=(j=1naj)ai
现在有 mmm 次询问,每次给定 x,tx,tx,t ,表示询问经过 ttt 次再编号后第 xxx 个人的编号。
由于答案可能很大,所以对 109+710^9+7109+7 取模。

输入描述:
第一行 2 个数 n,mn,mn,m ,表示人数和询问次数;
接下来一行 nnn 个数,表示 aia_iai
接下来 mmm 行,每行 2 个数 x,tx,tx,t ,描述一次询问。
输出描述:
mmm 行,第 iii 行 1 个数表示第 iii 次询问的答案对 109+710^9+7109+7取模的结果。
示例1
输入
4 3
1 2 3 4
1 0
2 2
4 1
输出
1
22
6
说明
初始编号:1 2 3 4
1 次再编号后:9 8 7 6
2 次再编号后:21 22 23 24
备注:
nnn ≤ 100000 , mmm ≤ 10000 , ttt ≤ 100000 , 1 ≤ aia_iai10910^9109

AC代码

#include<iostream>
using namespace std;
using ll = long long;
const int N = 1e5 + 5, mod = 1e9 + 7;
int n, m, a[N], s[N];
ll sum;
int main(){
    cin >> n >> m;//n个人问m次
    for(int i = 1; i <= n; i++){
        cin >> a[i];
        sum = (sum + a[i]) % mod;//算出再编号公式的被减数
    }
    
    for(ll i = 1, j = 1; i < 1e5; i++){
        s[i] = (j - s[i - 1] + mod) % mod;
        j = (j*(n - 1)) % mod;
    }
    
    while(m--){
       int x, t;
       cin >> x >> t;
       ll ans = sum * s[t];
       if(t & 1) ans = (ans - a[x] + mod) % mod;//t为奇数
       else ans = (ans + a[x] + mod) % mod;//t为偶数
       cout << ans << endl;
    }
    return 0;
}

代码分析

初始编号:1  2  3  4 sum = 10 

1 次再编号后:9  8  7  6 sum = 30

2 次再编号后:21  22  23  24 sum = 90

3次再编号后:69 68 67 66 sum = 270

4次再编号后:201 202 203 204 sum = 810

5次再编号后:539 538 537 536 sum = 2430

找每次编码后与第一次编码的规律
发现:
1.奇数次编号和偶数次编号尾号一致 ⇒\Rightarrow 分奇偶讨论
2.每次编号后sum的值规律为q=3q=3q=3的等比数列

总结

1.(k + mod) % mod可确保所得数为正
2. & 按位与操作:转换为二进制位后两个均为1才为1,其余都位0
3. int能存储的最大数:231−12^{31}-12311

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值