Solution 2020 1103 序列查詢

2022-05-05 17:30:08 字數 4596 閱讀 4575

describtion:

有乙個無限長的序列,給定 $k$,$mo$,滿足 $ x[i]=i \times  k \space\space mod \space \space mo $ 詢問這個序列第$ i $個數到第$ r $個數中,大於等於$ u $且小於等於$ v $的數有多少個。$ mod$ 表示取模,求餘,如: $10 mod 4=2$, $10 mod 2=0 $ $10 mod 3=1$。

input:

第一行六個數 $k$,$mo$,$i$,$r$,$u$,$v$,意義如上所述 。

output:

乙個數表示滿足要求的數的個數。

example:

3 10 4 7 2 8

30%資料滿足所有引數$ \le 10^3 $

100%資料滿足 $1\le$所有引數$ \le 10^ $,$i \le r$,$u \le v$

首先我們考慮$o(n)$的暴力做法

對於區間$[i,r]$,計算出每乙個數,看它的值是否在$[u,v]$之間(**過於簡單),但這樣做只能拿到三十分,回到題面我們觀察題目資料,n為$10^$,所以必須為$o(log_n)$的做法才能$ac$這道題,那麼接下來我們開始思考正解:

對於乙個數列題,在思考時最常規的優化方法就是利用字首和,考慮在本題中字首和的用法

即:$f(i,j)$表示前i個數中值小於等於j的數的個數

利用小小的容斥定理,此時的問題就轉換成了求$$(f(r,v)-f(r,u-1))-(f(i,v)-f(i,u-1))$$,而對於求$f(i,j)$似乎沒有什麼簡便的演算法,只能去遍歷,但我們又只能有$o(log_n)$的複雜度,應該怎麼去實現呢?回到題目,仔細觀察這個無限長的序列,就會有乙個驚人的發現:這個數列一定是有序的。我們用樣例資料來算20個看一看:

1

0-9203

6925

8147

3410-1950

3692

5814

7

非常明顯這個數列從$0$開始是每十個一迴圈的,在$[4,7]$中有三個數:$2\ 5\ 8$在$[2,8]$中,那麼在$[14,17]$同樣也只有三個數在$[2,8]$中,但對於乙個任意序列我們是不是都要求出它的迴圈節呢?我們繼續分析這個序列:

1

//若我們認為的去規定這個迴圈節的長度,我們看會發生什麼2//

我們規定長度為4

30-11為:40

3695

2581

6470

3

我們可以清楚地看到每乙個節的對應元素都增加了$2$,即:$$ \delta = len*k\%m =2 $$(這個應該很好理解)

在第乙個節中去找在值在$[2,8]$上的數為:$3\  6 $

然後是第二個節:$ 2\  5\  8 $

這個時候我們發現在第二個節中尋找範圍在$[2,8]$上的數,就相當於在第乙個節中尋找$[0,6]$的數(這個應該也很好理解),在第乙個節中$[0,6]$上的數為:$0\  3\  6$,乙個偉大的發現誕生了

第二個節中的$2\  5 \ 8$明顯就是在$0\  3 \ 6$的基礎上都加了$2$而已,利用這個$\delta$的值,我們就思考起來這個節的長度是不是和我們查詢數的個數無關

我們繼續考慮,在第三個節我們找$[2,8]$,利用前面發現的規律,就相當於在第乙個節中找$[-2,4]$的數,此時出現了負數,但顯然序列中不可能出現負數,我們可以思考$[-2,0]$這個負區間是怎麼來的,它應該是乙個數$p$,$p-num*delta$來的,而這個數一定不是負數,所以說明這個數加上$\delta \times num$後一定大於$m$,所以這個數$%m$的值一定在$[-2+m,m)$之間(此處建議自己在紙上算一算),此時我們就把這個區間重新轉換為了乙個正區間,那麼現在在第乙個節中尋找的範圍就應該是$[0,4]$和$[8,9]$,即:$0\  3\  6$,此時我們再次發現,$4\  7 \ 3$就是由這三個數變來的,為了簡化求在這個範圍的數的個數,利用小小的容斥,就相當於是用迴圈節的長度-迴圈節中值在$[4,7]$上的數的個數

到目前為止,我們就已經總結出了如何通過只維護乙個節來訪問整個序列的方法

**實現如下:

1

ll ans(ll k,ll m,ll n,ll l,ll r)

9 ll derta=(ll)step*k%m; //

derta為全**精華部分,代表每個step序列差值

10 sort(a,a+step); //

前step個排序,便於二分查詢(優化時間複雜度)

11 ll res=0,now; //

rest計數,now控制遍歷次數

12for(now=0;now+step<=n+1;now+=step)

19for(ll i=now;i<=n;i++)

24return

res;25}

2627

ll efind(ll k)

34return l+1

;35 }

主要功能實現後,整個程式就好實現了:

1 #include2

#define ll long long

3#define step 100000

4using

namespace

std;

56 ll a[step+5],b[step+5];7

8ll efind(ll k)

15return l+1;16

} 17

18ll ans(ll k,ll m,ll n,ll l,ll r)

25 ll derta=(ll)step*k%m; //

derta為全**精華部分,代表每個step序列變值

26 sort(a,a+step); //

前step個排序,便於二分查詢

27 ll res=0,now; //

rest計數,now控制遍歷次數

28for(now=0;now+step<=n+1;now+=step)

35for(ll i=now;i<=n;i++)

40return

res;41}

4243

ll count(ll k,ll n,ll a,ll b,ll low,ll upp)

4647

intmain()

當然還有乙個毒瘤的結構體寫法:

1 #include 2 #include 3 #include 4 #include 

5 #include 6 #include 7 #include 8 #include 9 #include 10 #include 11 #include 12 #include 13 #include 14 #include 15 #include 16 #include 17 #include 18 #include 19 #include 20 #include 21

22using

namespace

std;

2324

const

int step=100000;25

long

long a[step+5],b[step+5

];26

27class

modulesequence

2839

40long

long calc(long

long k,long

long m,long

long n,long

long l,long

long

r)41

57for (long

long i=now;i<=n;i++)

58 res+=((l<=r && b[i-now]>=l && b[i-now]<=r) || ((l>r) && (b[i-now]>=l || b[i-now]<=r)));

59return

res;60}

6162

long

long countelements(long

long k, long

long n, long

long a, long

long b, long

long lower, long

long

upper)

6366

};67

68int

main()

2020 1 10佇列(陣列模擬)

隊空 佇列中沒有任何元素。隊滿 佇列空間已全被占用。溢位 上溢 overflow 下溢 underflow 1.初始化 初始化狀態為front rear 0,即佇列裡沒有任何元素。void clear 2.判空 bool empty 3求佇列中實際元素的個數 int size 4.入隊 void p...

保稅物料的業務SOLUTION

區分保稅料件與非保稅料件用乙個料號還是倆個料號,都會影響倉庫 關務 製成 財務 研發等相關部門作業。solution1 設定乙個料號 優點 inv 倉庫 料號上沒有一物多料號的情況 bom wip 同乙個成品不需要設定多個 bom或者開立多工單 關務 向海關備案手冊 成品比較簡單,減少了料件項與成品...

命令列編譯Solution

c windows devenv.com microsoft r 開發環境 7.10.3077 版。c microsoft corp 1984 2001 保留所有權利。用法 devenv solutionfile projectfile anyfile.ext switches 可以呼叫 deven...