算法-数论

 C-小红的数组查询(二)_牛客周赛 Round 95

 思路:不难看出a数组是有循环的

d=3,p=4时,a数组:1、0、3、21、0、3、2.......  最小循环节为4,即最多4种不同的数

d=4,p=6时,a数组:1、5、31、5、3.......最小循环节为3

d=4,p=10时,a数组:1、5、9、3、71、5、9、3、7.......最小循环节为5

可以得出,最小循环节T=p / gcd(d,p)

 

ans=min(询问的区间长度,最小循环节)

ans=min(r-l+1,T)

特殊情况:p=1时,a数组:1、0、0、0........(任何数对1取模均为0)

l=1,r>1时,ans=2

其余,ans=1

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main() {
    ll d,p,q;
    cin>>d>>p>>q;
    // 将d对p取模,因为后续的计算是基于模p的
    d = d % p;
    // 计算d和p的最大公约数g
    ll g = __gcd(d, p);
    // 计算T,即周期长度,T = p / g
    ll T = p / g;
    // 处理q次询问
    while (q--) {
        ll l, r;
        cin >> l >> r;
        // 特殊情况:如果p == 1,那么所有元素都是0(因为任何数mod 1都是0)
        if (p == 1) {
            // 如果区间长度大于1,那么只有0和1两种元素(因为a1=1,其他都是0)
            ll ans = 1;
            if (l == 1 && r > 1) {
                ans++;
            }
            cout << ans << endl;
            continue;
        }
        // 计算区间内的元素种类数
        // 如果区间长度小于T,那么元素种类数就是区间长度,
        // 否则,元素种类数就是T
        cout << min(r - l + 1, T) << endl;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值