tokiomarine2020 F(匹克定理)

F Triangles
匹克定理:
若多边形顶点坐标都为整点,令其面积为 S S S,其内部整点数为 n e ne ne,其边界上的整点数为 w a wa wa,则有 S = n e + w a / 2 − 1 S=ne+wa/2-1 S=ne+wa/21在这里插入图片描述
设三个点为 ( a , 0 ) , ( 0 , b ) , ( w , c ) (a,0),(0,b),(w,c) (a,0),(0,b),(w,c),其中 c > = b c>=b c>=b,对与 c < b c<b c<b由对称性可得。对于选其它不同边上的点可转换为同样的情况。

根据匹克定理,有 2 ∗ n e = 2 ∗ S − w a + 2 < = 2 ∗ k 2*ne=2*S-wa+2<=2*k 2ne=2Swa+2<=2k
其中 2 ∗ S = a ∗ ( c − b ) + b ∗ w 2*S=a*(c-b)+b*w 2S=a(cb)+bw(根据多边形面积公式可得)。
w a = ( w − a , c ) + ( a , b ) + ( c − b , w ) wa=(w-a,c)+(a,b)+(c-b,w) wa=(wa,c)+(a,b)+(cb,w) ( a , b ) (a,b) (a,b)表示 g c d ( a , b ) gcd(a,b) gcd(a,b)

枚举 a a a c − b c-b cb
则有:
a ∗ ( c − b ) + w ∗ b − ( w − a , c ) − ( a , b ) − ( c − b , w ) + 2 < = 2 ∗ k a*(c-b)+w*b-(w-a,c)-(a,b)-(c-b,w)+2<=2*k a(cb)+wb(wa,c)(a,b)(cb,w)+2<=2k
==> w ∗ b − ( w − a , c ) − ( a , b ) < = 2 ∗ k − a ∗ ( c − b ) + ( c − b , w ) − 2 w*b-(w-a,c)-(a,b)<=2*k-a*(c-b)+(c-b,w)-2 wb(wa,c)(a,b)<=2ka(cb)+(cb,w)2

令右式为 R R R,左式为 L L L,由于 ( w − a , c ) + ( a , b ) < = w (w-a,c)+(a,b)<=w (wa,c)+(a,b)<=w
w ∗ ( b − 1 ) < = L < = w ∗ b w*(b-1)<=L<=w*b w(b1)<=L<=wb
b < = R / w b<=R/w b<=R/w,有 L < = b ∗ w < = R L<=b*w<=R L<=bw<=R,不等式恒成立。
b > R / w + 1 b>R/w+1 b>R/w+1,有 L > = ( b − 1 ) ∗ w > R L>=(b-1)*w>R L>=(b1)w>R,不等式恒不成立。
R / w < b < = R / w + 1 R/w<b<=R/w+1 R/w<b<=R/w+1,将所有值代入不等式判断即可。

R > = w ∗ ( b − 1 ) 且 b > = 1 R>=w*(b-1)且b>=1 R>=w(b1)b>=1,故 R > = 0 R>=0 R>=0
则有 2 ∗ k − a ∗ ( c − b ) + ( c − b , w ) − 2 > = 0 2*k-a*(c-b)+(c-b,w)-2>=0 2ka(cb)+(cb,w)2>=0,需要枚举的 a a a c − b c-b cb的对数为 M l o g ( M ) Mlog(M) Mlog(M) ( M = 1 e 5 ) (M=1e5) (M=1e5)

总时间复杂度为 M l o g ( M ) l o g ( M ) Mlog(M)log(M) Mlog(M)log(M)

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
typedef long long ll;
int h,w,k;
ll solve(int w,int h)
{
    ll ans=0;
    for(int a=1;a<w;a++)
        for(int c_b=0;c_b<h;c_b++)
    {
        int R=2*k-a*c_b+__gcd(c_b,w)-2;
        if(R<0) break;
        int low=min(h-1-c_b,R/w);
        ans+=c_b==0?low:low*2;
        low++;
        if(low+c_b<h&&w*low-__gcd(w-a,low+c_b)-__gcd(a,low)<=R)
            ans+=c_b==0?1:2;
    }
    return ans*2;
}
int main()
{
    scanf("%d%d%d",&w,&h,&k);
    printf("%lld\n",solve(w,h)+solve(h,w));
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值