南阳 oj Mod 题目1317

1、题目信息

Mod

时间限制: 4000 ms  |  内存限制: 65535 KB
难度: 2
描述
mod是取余运算,在程序中用符号"%"来表示。

如3 % 7 = 3,7 % 5 = 2,0 % 4 = 0。

Ocean用巧妙的方法得到了一个序列,该序列有 NN 个元素,我们用数组 aa 来记录(下标从 00N1

Ocean定义f[i] = (((i % a[0]) % a[1]) % ...) % a[N-1]。

现在Ocean会给出Q次查询,每次给定一个区间[L, R],他想快速知道f[L] + ... + f[R]的值。
输入
第一行输入一个整数T,代表有T组测试数据。
每组数据占多行,第一行输入一个整数N,代表元素个数。
下面一行输入N个整数ai。
下面一行输入一个整数Q,代表Q次查询。
接下来Q行,每行输入两个整数L, R,代表查询的区间。

注:1 <= T <= 20,1 <= N,Q <= 1000,1 <= ai <= 100000,1 <= L <= R <= 100000。
输出
对每组数据,依次输出Q行,每行输出对应的查询结果。
样例输入
2
5 
5 4 3 2 1
4
1 100000
2 100000
3 100000
4 100000
5
5 5 5 5 5
4
1 100000
2 100000
3 100000
4 100000
样例输出
0
0
0
0
200000
199999
199997
199994

2、思路

    1)这个题目数据规模比较大,适合使用打表法(一次性将所有数据计算出来,存入数组中)

    2)多次取余,如果后面的除数大于前面的,无效可以去除

    3)使用二分查找(这里使用c++模板库的lower_bound()函数)

    4)如果除数列表中有1,则所有结果都是0

3、代码

#include <stdio.h>
#include <algorithm>
#include <math.h>
#define MaxSize_1 1010
#define MaxSize_2 100010
using namespace std;

int a[MaxSize_2]={0};//存放打表数据
int b[MaxSize_1];//存放除数
int main(){
    int t,m;
    scanf("%d",&t);
    while(t--){
        int temp,flag=0,index=0;//temp用来暂时存放除数;flag标记除数序列是否有1;index作为除数序列的下标
        scanf("%d",&m);
        scanf("%d",&b[0]);//首先存取除数中的第一个,方便判断后续除数的大小,进而选择是否保留
        
        //这里除数序列取负,是为了使用lower_bound()函数时,不断找到小于被除数的除数
        b[0]=-b[0];
        for(int i=1;i<m;i++){
            scanf("%d",&temp);
            if(temp==1) flag=1;
            else{
                if(temp<abs(b[index])){
                    b[++index]=-temp;
                }
            }
        }

        if(!flag){//如果b数组中没有1,打标
            for(int i=1;i<MaxSize_2;i++){
                int k=i;
                for(int j;;){
                    //lower_bound()函数返回的是大于等于待查数的下标,否则返回数组的右边界(注意右边界是开区间)
                    j=lower_bound(b,b+index+1,-k)-b;
                    if(j==index+1) break;
                    k=k%(-b[j]);
                }
                a[i]=a[i-1]+k;
            }
        }
        int q,l,r;
        scanf("%d",&q);
        while(q--){
            scanf("%d%d",&l,&r);
            if(flag) printf("0\n");
            else{
                printf("%d\n",a[r]-a[l-1]);
            }
        }
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/sicauliuy/article/details/80188211