[atARC111E]Simple Math 3

首先,必然要有$(a+ci)-(a+bi)+1<d$,因此$(c-b)ile d-2$,即$ile lfloorfrac{d-2}{c-b} floor$

此时,$[a+bi,a+ci]$中不存在$d$的倍数,当且仅当$lfloorfrac{a+bi-1}{d} floor=lfloorfrac{c+bi}{d} floor$,同时两者之差不大于2,因此可以通过求和来统计,即$n-sum_{i=1}^{n}lfloorfrac{a+ci}{d} floor-lfloorfrac{a+bi-1}{d} floor$(其中$n=lfloorfrac{d-2}{c-b} floor$)

这两个式子是类似的,因此可以仅考虑$sum_{i=1}^{n}lfloorfrac{a+ci}{d} floor$

将后者用1累加的形式来表示,即$sum_{i=1}^{n}sum_{1le jle lfloorfrac{a+ci}{d} floor}1$

调换枚举顺序,令$n'=lfloorfrac{a+cn}{d} floor$,因此即$sum_{j=1}^{n'}sum_{1le ile n,jle lfloorfrac{a+ci}{d} floor}1$

考虑$jle lfloorfrac{a+ci}{d} floor$,改为用$j$来限制$i$,即$lceilfrac{jd-a}{c} ceil=lfloorfrac{jd-a+c-1}{c} floorle ile n$

同时注意到$a<d$且$jge 1$,即保证了$lfloorfrac{jd-a+c-1}{c} floorge 1$

再将后者1的累加展开,即$sum_{j=1}^{n'}n-lfloorfrac{jd-a+c-1}{c} floor+1=n'(n+1)-sum_{j=1}^{n'}lfloorfrac{(c-a-1)+jd}{c} floor$

因此,即记$f(n,a,c,d)=sum_{i=1}^{n}max(lfloorfrac{a+ci}{d} floor,0)$,则$f(n,a,c,d)=n'(n+1)-f(n',c-a-1,d,c)$

另外,$f(n,a,c,d)$还有以下变换来规范其形式,即:

1.若$age d$,$f(n,a,c,d)=f(n,a mod d,c,d)+lfloorfrac{a}{d} floor n$

2.若$a<0$,$f(n,a,c,d)=f(n,a+kd,c,d)-kn$(其中$k=lfloorfrac{-a+d-1}{d} floor$)

3.若$cge d$,$f(n,a,c,d)=f(n,a,c mod d,d)+lfloorfrac{c}{d} floor{n+1choose 2}$

4.若$c=0$,$f(n,a,c,d)=0$

注意到其关于$(c,d)$的变换形式与扩展欧几里得相同,因此复杂度为$o(log_{2}d)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 int t,a,b,c,d;
 5 ll n;#include<bits/stdc++.h>
 6 using namespace std;
 7 #define ll long long
 8 int t,a,b,c,d;
 9 ll n;
10 ll f(ll n,int a,int c,int d){
11     if (a>=d)return f(n,a%d,c,d)+(a/d)*n;
12     if (a<0){
13         int k=(-a+d-1)/d;
14         return f(n,a+k*d,c,d)-k*n;
15     }
16     if (c>=d)return f(n,a,c%d,d)+(n+1)*n/2*(c/d);
17     if (!c)return 0;
18     ll nn=(a+c*n)/d;
19     return nn*(n+1)-f(nn,c-a-1,d,c);
20 }
21 int main(){
22     scanf("%d",&t);
23     while (t--){
24         scanf("%d%d%d%d",&a,&b,&c,&d);
25         n=(d-2)/(c-b);
26         printf("%lld
",n-f(n,a,c,d)+f(n,a-1,b,d));
27     }
28 } 
29 ll f(ll n,int a,int c,int d){
30     if (a>=d)return f(n,a%d,c,d)+(a/d)*n;
31     if (a<0){
32         int k=(-a+d-1)/d;
33         return f(n,a+k*d,c,d)-k*n;
34     }
35     if (c>=d)return f(n,a,c%d,d)+(n+1)*n/2*(c/d);
36     if (!c)return 0;
37     ll nn=(a+c*n)/d;
38     return nn*(n+1)-f(nn,c-a-1,d,c);
39 }
40 int main(){
41     scanf("%d",&t);
42     while (t--){
43         scanf("%d%d%d%d",&a,&b,&c,&d);
44         n=(d-2)/(c-b);
45         printf("%lld
",n-f(n,a,c,d)+f(n,a-1,b,d));
46     }
47 } 
View Code
原文地址:https://www.cnblogs.com/PYWBKTDA/p/14307667.html