[atARC111E]Simple Math 3

首先,必然要有$(a+ci)-(a+bi)+1<d$,因此$(c-b)i\le d-2$,即$i\le \lfloor\frac{d-2}{c-b}\rfloor$

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

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

将后者用1累加的形式来表示,即$\sum_{i=1}^{n}\sum_{1\le j\le \lfloor\frac{a+ci}{d}\rfloor}1$

调换枚举顺序,令$n'=\lfloor\frac{a+cn}{d}\rfloor$,因此即$\sum_{j=1}^{n'}\sum_{1\le i\le n,j\le \lfloor\frac{a+ci}{d}\rfloor}1$

考虑$j\le \lfloor\frac{a+ci}{d}\rfloor$,改为用$j$来限制$i$,即$\lceil\frac{jd-a}{c}\rceil=\lfloor\frac{jd-a+c-1}{c}\rfloor\le i\le n$

同时注意到$a<d$且$j\ge 1$,即保证了$\lfloor\frac{jd-a+c-1}{c}\rfloor\ge 1$

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

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

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

1.若$a\ge d$,$f(n,a,c,d)=f(n,a\ mod\ d,c,d)+\lfloor\frac{a}{d}\rfloor n$

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

3.若$c\ge d$,$f(n,a,c,d)=f(n,a,c\ mod\ d,d)+\lfloor\frac{c}{d}\rfloor{n+1\choose 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",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",n-f(n,a,c,d)+f(n,a-1,b,d));
46     }
47 } 
View Code

 

posted @ 2021-01-21 14:03  PYWBKTDA  阅读(166)  评论(0编辑  收藏  举报