模擬賽 同餘

Problem 3. 同餘
Input file: congruence.in
Output file: congruence.out
Time limit: 1 second
Memory limit: 256 MB
⼩ X 望着草稿紙上的數列,結合⾃⼰對同餘的粗淺認識,又想到了⼀個新問題。
對於⼀個長度爲 n 的數列 {ai},每次詢問將給出⼀組數 l, r, p, q,⼩ X 想知道有多少個 i 滿⾜
l ≤ i ≤ r 且 ai ≡ q (mod p)。
⼩ X 沉迷這個問題⽆法⾃拔,因此⼀共進⾏了 m 次詢問。
Input
第⼀⾏包含兩個整數 n, m。
第⼆⾏包含 n 個整數,表⽰數列 {ai}。
接下來 m ⾏,每⾏包含四個整數 l, r, p, q,表⽰⼀次詢問。
Output
m ⾏,每⾏包含⼀個整數,表⽰該次詢問的答案。
Example
congruence.in congruence.out
5 2
1 5 2 3 7
1 3 2 1
2 5 3 0
2
1
Scoring
• 對於 20% 的數據,ai ≤ 1。
• 對於 60% 的數據,ai ≤ 100。
• 對於 100% 的數據,1 ≤ m ≤ 105,1 ≤ l ≤ r ≤ n ≤ 105,0 ≤ q < p ≤ 10000,0 ≤ ai ≤ 10000。

分塊加前綴和竟然能a。

#include<cstdio>
#include<cstring>
#include<utility>
#include<algorithm>
#include<iostream>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdlib>
#include<ctime>
using namespace std;
inline int read()
{
    char ch='*';
    while(!isdigit(ch=getchar()));
    int num=ch-'0';
    while(isdigit(ch=getchar()))num=num*10+ch-'0';
    return num;
}
int n;
int m,p,q,l,r;
int s[320][10005];
int k[320][10005];
int a[100005];
int ave;
int rr;
int maxn;
int main()
{
    freopen("congruence.in","r",stdin);
    freopen("congruence.out","w",stdout);   
    n=read();
    m=read();
    int x;
    ave=(int) sqrt(n);
    for(int i=1;i<=n;i++)
    {
        a[i]=read();
        k[i/ave][a[i]]++;
        maxn=max(maxn,a[i]);    
    }
    for(int i=0;i<=maxn;i++)
    {
        s[0][i]=k[0][i];
    }
    for(int i=1;i<=ave+1;i++)
    {
        for(int j=0;j<=maxn;j++)
        {
            s[i][j]=s[i-1][j]+k[i][j];
        }
    }
    int ans;    
    for(int i=1;i<=m;i++)
        {
            l=read();r=read();p=read();q=read();ans=0;
            if(l/ave>r/ave-2){
                for(int i=l;i<=r;i++)
                     ans+=(a[i]%p==q);      
                printf("%d\n",ans);
            }
            else if(p==1)   printf("%d\n",r-l+1);
            else {
                rr=r/ave-1;
                int ll=l/ave+1;
                    for(int j=q;j<=maxn;j+=p)               
                        ans+=s[rr][j]-s[ll-1][j];                           
                if(l%ave==0) {
                    l=l/ave;
                    for(int i=q;i<=maxn;i+=p)               
                        ans+=k[l][i];               
                }
                else for(int i=l;i%ave;i++)
                    ans+=(a[i]%p==q);           
                if(r%ave==ave-1)
                {
                    r=r/ave;
                    for(int i=q;i<=maxn;i+=p)
                    ans+=k[r][i];               
                }
                else for(int i=r;i%ave!=ave-1;i--)
                    ans+=(a[i]%p==q);
                printf("%d\n",ans);
            }
        }   
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章