机试真题-前缀和 XC 24.05.06.03
1. 题目描述
俊子哥拿到一个数组,他想知道区间[ l l l, r]中所有元素乘积模6之后的结果为多少。共有q次查询
输入描述
第一行输入两个正整数n,q,代表小红拿到的数组大小以及询问次数。
第二行输入n个正整数
a
i
a_i
ai,代表数组中的元素。
接下来的q行,每行输入两个正整数
l
l
l,r,代表询问的区间为第
l
l
l个数到第r个数的乘积。
1<=n, q<=
1
0
5
10^5
105
1<=
a
i
a_i
ai<=
1
0
9
10^9
109
1<=
l
l
l<=r<=n
输出描述
输出q行,第 i i i行代表第 i i i次询问的结果
示例
输入
5 3
1 2 3 4 5
2 4
4 5
1 2
输出
0
2
2
2. 解题思路
首先对数组的每个元素对6取模来进行预处理,然后使用前缀和来统计[ l l l,r]区间中的数所有2、3、5、0的个数(小于6的数的最小集,4可以由2平方获得),然后利用快速幂来进行求解。
#include <iostream>
#include <vector>
using namespace std;
int qpow(int a, int n){
int ans = 1;
while(n){
if(n&1)
ans *= a % 6;
a*=a % 6;
n>>=1;
}
return ans;
}
int main(){
int n,q;
cin>>n>>q;
vector<int> a(n,0);
vector<int> p0(n, 0),p2(n, 0),p3(n, 0), p5(n, 0);
int x0=0,x2=0,x3=0,x5=0;
for(int i=0;i<n;i++)
{
cin>>a[i];
a[i] %= 6; //直接就对初始输入进行模操作
if(a[i] == 0)
x0++;
else if(a[i] == 2)
x2++;
else if(a[i] == 3)
x3++;
else if(a[i]==4)
x2 += 2; //注意2*2=4,所以不用保存4个数,直接x2加上2
else
x5++;
p0[i]=x0;
p2[i] = x2;
p3[i] = x3;
p5[i] = x5;
}
while(q--){
int l, r;
cin>>l>>r;
x0 = p0[r] - p0[l-1];
if(x0 != 0){
cout<<0<<endl;
continue;
}
x2 = p2[r] - p2[l-1];
x3 = p3[r] - p3[l-1];
x5 = p5[r] - p5[l-1];
int ans = qpow(2, x2) * qpow(3, x3) * qpow(5, x5) % 6;
cout<<ans<<endl;
}
return 0;
}