1. 程式人生 > 其它 >CF1342C Yet Another Counting Problem

CF1342C Yet Another Counting Problem

考察對取模“週期性”的理解。

給定兩個數 \(a,b\),進行 \(q\) 次詢問,對於每次詢問給出回答——在 \([l,r]\) 中,滿足以下條件的 \(x\) 的個數:\((x \mod a) \mod b=(x \mod b) \mod a\) 的數的個數。保證 \(l_i,r_i\le 10^{18}\)

什麼時候會合法呢?不難想到取模的週期性

  • 如果 \(x \mod a=y\),則 \((x+a) \mod a=y\),進而推得 \((x+a\times k) \mod a=y\)
  • 如果 \(x \mod b=y\),則 \((x+b) \mod b=y\),進而推得 \((x+b\times k) \mod b=y\)
  • 如果 \((x \mod a) \mod b=(x \mod b) \mod a\),不難發現,\(((x+k\times ab) \mod a)\mod b=((x+k\times ab) \mod b)\mod a\)

迴圈! 迴圈節是 \(a\times b\)。故此,我們只需要預處理出 \(0 \to a\times b-1\) 範圍內合法的數,就可以推到任意區間。具體公式是 \(\lceil\frac{x}{ab}\rceil \times sum_{ab-1}+sum_{x\mod ab}\)

時間複雜度 \(O(ab+q)\)

下面是預處理:

t=a*b;
for(reg int i=0;i<t;++i){
	if((i%a%b)!=(i%b%a)) s[i]=1;
	for(reg int i=1;i<a*b;++i) s[i]+=s[i-1];
}

下面是查詢函式:

inline LL ask(LL x){
	if(x==0) return 0;
	LL y=x/t,res=s[t-1]*y;
	x-=y*t;
	return res+s[x];
}

THE END