传送门
题解:
刚拿到的时候还以为是什么类欧几里得神仙题。
这道题要抄代码倒是很好抄,推导很麻烦。
首先当 g c d gcd gcd不为 1 1 1的时候,设 g = g c d ( a , b , c ) g=gcd(a,b,c) g=gcd(a,b,c),我们可以轻易转化为 g 2 g^2 g2个小的平面来算。
设 F ( a , b , c ) F(a,b,c) F(a,b,c)表示当 g c d ( a , b , c ) = 1 gcd(a,b,c)=1 gcd(a,b,c)=1的时候的答案,先给一个结论,只想抄代码的可以拿了直接滚:
2 ⋅ F ( a , b , c ) = a ⋅ b + b ⋅ c + c ⋅ a − g c d ( a , b ) ⋅ g c d ( a , c ) ⋅ g c d ( b , c ) 2\cdot F(a,b,c)=a\cdot b+b\cdot c+c\cdot a-gcd(a,b)\cdot gcd(a,c)\cdot gcd(b,c) 2⋅F(a,b,c)=a⋅b+b⋅c+c⋅a−gcd(a,b)⋅gcd(a,c)⋅gcd(b,c)
我们发现一个问题,在三者 g c d = 1 gcd=1 gcd=1的情况下,两两的 g c d gcd gcd不一定为 1 1 1。
接下来以 a = 15 , b = 10 , c = 6 a=15,b=10,c=6 a=15,b=10,c=6为例子进行探讨。(官方题解就是这个例子)
开始官方题解的神仙推导:
首先拿到主视图(用几何画板硬生生画出来的):
底为 a a a高为 b b b,首先看图中紫色的部分,这部分中所有被染到的格子(只染到顶点不算)在截面中都会被切掉一次。
显然染掉的格子总数为 S 1 = a ⋅ b + a + b − g c d ( a , b ) 2 S_1=\dfrac{a\cdot b+a+b-gcd(a,b)}{2} S1=2a⋅b+a+b−gcd(a,b)。
简单证明一下:
显然我们可以根据对称性来考虑,则 S 1 = a ⋅ b + k 1 2 S_1=\dfrac{a\cdot b+k_1}{2} S1=2a⋅b+k1,其中 k 1 k_1 k1为对角线穿过的格子总数。
显然 k 1 k_1 k1可以考虑穿过了几次横轴和纵轴,一共 a + b a+b a+b次,有几次是横轴和纵轴一起穿过的,一共 g c d ( a , b ) gcd(a,b) gcd(a,b)次,则 k 1 = a + b − g c d ( a , b ) k_1=a+b-gcd(a,b) k1=a+b−gcd(a,b)
然后,我们把主视图向后推
c
c
c个单位,把所有
c
c
c条截面上的交线画出来:
除了这里紫色区域的斜边外,所有剩下线段在主视图中交上了的格子全部都会在平移后对答案产生贡献需要计算。
假设线段从上到下依次为第 1 1 1条到第 c c c条,其中第 i i i条线段交的格子数量为 k i k_i ki。
则答案为 F ( a , b , c ) = S 1 + ∑ i = 2 c k i F(a,b,c)=S_1+\sum\limits_{i=2}^ck_i F(a,b,c)=S1+i=2∑cki
2 ⋅ F ( a , b , c ) = a b − k 1 + 2 ⋅ ∑ i = 1 c k i 2\cdot F(a,b,c)=ab-k_1+2\cdot \sum\limits_{i=1}^ck_i 2⋅F(a,b,c)=ab−k1+2⋅i=1∑cki
仿照计算 k 1 k_1 k1的时候,对于所有 k i k_i ki,我们计算他横跨了多少行,多少列,跨过多少个顶点。
对于 i i i,分别设以上三个量为 r i , c i , p i r_i,c_i,p_i ri,ci,pi
为了方便,以下全部都求 2 ⋅ F ( a , b , c ) 2\cdot F(a,b,c) 2⋅F(a,b,c)
顶点我们规定必须严格在紫色区域内。
表达式为 2 ⋅ F ( a , b , c ) = a b − k 1 + 2 c + 2 ⋅ ( ∑ i = 1 c r i + ∑ i = 1 c c i − ∑ i = 1 c p i ) 2\cdot F(a,b,c)=ab-k_1+2c+2\cdot(\sum_{i=1}^cr_i+\sum_{i=1}^cc_i-\sum_{i=1}^c p_i) 2⋅F(a,b,c)=ab−k1+2c+2⋅(i=1∑cri+i=1∑cci−i=1∑cpi)
则现在要求 ∑ i = 1 c r i , ∑ i = 1 c c i , ∑ i = 1 c p i \sum\limits_{i=1}^cr_i,\sum\limits_{i=1}^cc_i,\sum\limits_{i=1}^cp_i i=1∑cri,i=1∑cci,i=1∑cpi
现在算一下 ∑ c i \sum c_i ∑ci, ∑ r i \sum r_i ∑ri同理。
这个地方我觉得官方题解在口胡,我说得稍微详细一点。
直接考虑每条线的横坐标坐标可以得到 c i = ⌈ ( c − i + 1 ) ⋅ a c ⌉ c_i=\lceil\dfrac{(c-i+1)\cdot a}{c}\rceil ci=⌈c(c−i+1)⋅a⌉,则:
∑ i = 1 c c i = ∑ i = 1 c ⌈ i ⋅ a c ⌉ = ∑ i = 1 c i ⋅ a c + ∑ i = 1 c c − ( i ⋅ a ) % c c = ∑ i = 1 c i ⋅ a c + ∑ i = 1 c i ⋅ a % c c \begin{aligned} \sum_{i=1}^cc_i&=&&\sum_{i=1}^c\lceil\frac{i\cdot a}{c}\rceil\\ &=&&\sum_{i=1}^c\frac{i\cdot a}{c}+\sum_{i=1}^c\frac{c-(i\cdot a)\%c}{c}\\ &=&&\sum_{i=1}^c\frac{i\cdot a}{c}+\sum_{i=1}^c\frac{i\cdot a\%c}{c}\\ \end{aligned} i=1∑cci===i=1∑c⌈ci⋅a⌉i=1∑cci⋅a+i=1∑ccc−(i⋅a)%ci=1∑cci⋅a+i=1∑cci⋅a%c
两部分乘 2 2 2算一下:
2 ⋅ ∑ i = 1 c i ⋅ a c = ( c + 1 ) ⋅ a 2 ⋅ ∑ i = 1 c i ⋅ a % c c = g c d ( a , c ) ⋅ ( c g c d ( a , c ) − 1 ) = c − g c d ( a , c ) \begin{aligned} 2\cdot \sum_{i=1}^c\frac{i\cdot a}{c}&=&&(c+1)\cdot a\\ 2\cdot \sum_{i=1}^c\frac{i\cdot a\%c}{c}&=&&gcd(a,c)\cdot(\frac{c}{gcd(a,c)}-1)=c-gcd(a,c) \end{aligned} 2⋅i=1∑cci⋅a2⋅i=1∑cci⋅a%c==(c+1)⋅agcd(a,c)⋅(gcd(a,c)c−1)=c−gcd(a,c)
有: ∑ i = 1 c c i = a ⋅ c + a + c − g c d ( a , c ) \sum_{i=1}^cc_i=a\cdot c+a+c-gcd(a,c) ∑i=1cci=a⋅c+a+c−gcd(a,c)
同理 ∑ i = 1 c r i = b ⋅ c + b + c − g c d ( b , c ) \sum_{i=1}^cr_i=b\cdot c+b+c-gcd(b,c) ∑i=1cri=b⋅c+b+c−gcd(b,c)
然后考虑算 ∑ i = 1 c p i \sum_{i=1}^cp_i ∑i=1cpi。
算一下紫色区域内部三线交点的个数,还是考虑计算全图,加上对角线上的 g c d ( a , b ) − 1 gcd(a,b)-1 gcd(a,b)−1个点之后除以 2 2 2。
发现一共有 g c d ( a , b ) ⋅ g c d ( a , c ) − 1 gcd(a,b)\cdot gcd(a,c)-1 gcd(a,b)⋅gcd(a,c)−1条线上有 g c d ( b , c ) gcd(b,c) gcd(b,c)个点,其中有 g c d ( a . c ) − 1 gcd(a.c)-1 gcd(a.c)−1条线上有 1 1 1个点不在内部。
则 2 ⋅ ∑ i = 1 c p i = ( g c d ( a , b ) ⋅ g c d ( a , c ) − 1 ) ⋅ g c d ( b , c ) − ( g c d ( a , c ) − 1 ) + g c d ( a , b ) − 1 = g c d ( a , b ) ⋅ g c d ( a , c ) ⋅ g c d ( b , c ) + g c d ( a , b ) − g c d ( b , c ) − g c d ( a , c ) \begin{aligned} 2\cdot \sum_{i=1}^cp_i&=&&(gcd(a,b)\cdot gcd(a,c)-1)\cdot gcd(b,c)-(gcd(a,c)-1)+gcd(a,b)-1\\ &=&&gcd(a,b)\cdot gcd(a,c)\cdot gcd(b,c)+gcd(a,b)-gcd(b,c)-gcd(a,c) \end{aligned} 2⋅i=1∑cpi==(gcd(a,b)⋅gcd(a,c)−1)⋅gcd(b,c)−(gcd(a,c)−1)+gcd(a,b)−1gcd(a,b)⋅gcd(a,c)⋅gcd(b,c)+gcd(a,b)−gcd(b,c)−gcd(a,c)
把上面一大坨东西合并起来
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const
cs int mod=1e9+7,inv2=mod+1>>1;
ll a,b,c;
signed main(){
int T;std::cin>>T;
while(T--){
std::cin>>a>>b>>c;
ll g=std::__gcd(a,std::__gcd(b,c));
a/=g,b/=g,c/=g;
ll ab=std::__gcd(a,b),bc=std::__gcd(b,c),ac=std::__gcd(a,c);
a%=mod,b%=mod,c%=mod;
ab%=mod,bc%=mod,ac%=mod;
g%=mod,g=g*g%mod*inv2%mod;
std::cout<<(a*b+b*c+a*c-ab*bc%mod*ac%mod+mod)%mod*g%mod<<"\n";
}
return 0;
}