【学习笔记】Triangles
套一下公式然后完
根据对称性,不妨考虑 ( 0 , i ) , ( j , 0 ) , ( W , k ) (0,i),(j,0),(W,k) (0,i),(j,0),(W,k)围成的三角形,同时假设 i < k i<k i<k。
套用 Pick \text{Pick} Pick定理: 2 S = a + b − 2 2S=a+b-2 2S=a+b−2
得到 j ( k − i ) + W i = 2 a + gcd ( i , j ) + gcd ( W − j , k ) + gcd ( W , k − i ) − 2 j(k-i)+Wi=2a+\gcd(i,j)+\gcd(W-j,k)+\gcd(W,k-i)-2 j(k−i)+Wi=2a+gcd(i,j)+gcd(W−j,k)+gcd(W,k−i)−2
既然前面假设 k > i k>i k>i,那么我们令 d = k − i d=k-i d=k−i,这样所有数都是正数。
j d + W i = 2 a + gcd ( i , j ) + gcd ( W − j , k ) + gcd ( W , k − i ) − 2 jd+Wi=2a+\gcd(i,j)+\gcd(W-j,k)+\gcd(W,k-i)-2 jd+Wi=2a+gcd(i,j)+gcd(W−j,k)+gcd(W,k−i)−2
瞪眼法不难看出此时 j , d j,d j,d的对数是调和级数。那么我们枚举 j , d j,d j,d,这样只剩下变量 i i i:
j d − gcd ( W , d ) + 2 = 2 a + gcd ( i , j ) + gcd ( W − j , d + i ) − W i jd-\gcd(W,d)+2=2a+\gcd(i,j)+\gcd(W-j,d+i)-Wi jd−gcd(W,d)+2=2a+gcd(i,j)+gcd(W−j,d+i)−Wi
换成不等式:
W i ≤ − j d + gcd ( W , d ) + gcd ( i , j ) + gcd ( W − j , d + i ) − 2 + 2 K Wi\le -jd+\gcd(W,d)+\gcd(i,j)+\gcd(W-j,d+i)-2+2K Wi≤−jd+gcd(W,d)+gcd(i,j)+gcd(W−j,d+i)−2+2K
不难发现当 i ≤ ⌊ − j d + gcd ( W , d ) − 2 + 2 K W ⌋ i\le \lfloor\frac{-jd+\gcd(W,d)-2+2K}{W}\rfloor i≤⌊W−jd+gcd(W,d)−2+2K⌋时一定合法,因此只需检验 ⌊ − j d + gcd ( W , d ) − 2 + 2 K W ⌋ + 1 \lfloor\frac{-jd+\gcd(W,d)-2+2K}{W}\rfloor+1 ⌊W−jd+gcd(W,d)−2+2K⌋+1即可,可以 O ( 1 ) O(1) O(1)判断。
复杂度 O ( n log 2 n ) O(n\log^2 n) O(nlog2n)。
#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
#define db long double
#define cpx complex<db>
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
int W,H,K;
ll res;
int gcd(int x,int y){
return y==0?x:gcd(y,x%y);
}
ll solve(int W,int H){
ll res=0;
for(int j=1;j<W;j++){
for(int d=1;d<H&&j*d<=K*2+W;d++){
int i=(-j*d+gcd(W,d)-2+2*K)/W;i=min(i,H-d-1);i=max(i,0);
assert(i>=0);res+=i;
if(i!=H-d-1&&W*(i+1)<=-j*d+gcd(W,d)+gcd(i+1,j)+gcd(W-j,d+i+1)-2+2*K)res++;
}
}res<<=1;
for(int j=1;j<W;j++){
int i=(2*K+W-2)/W;i=min(i,H-1);i=max(i,0);
assert(i>=0);res+=i;
if(i!=H-1&&W*(i+1)<=2*K+gcd(i+1,j)+gcd(W-j,i+1)+W-2)res++;
}return res;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>W>>H>>K;
cout<<(solve(W,H)+solve(H,W)<<1);
}

浙公网安备 33010602011771号