USACO-Section3.4 Electric Fences【数学】

题目描述:

在本题中,格点是指横纵坐标皆为整数的点。

为了圈养他的牛,农夫约翰建造了一个三角形的电网。他从原点(0,0)牵出一根通电的电线,连接格点(n,m)(0<=n<32000,0 < m<32000),再连接格点(p,0)(p>0),最后回到原点。

牛可以在不碰到电网的情况下被放到电网内部的每一个格点上(十分苗条的牛)。如果一个格点碰到了电网,牛绝对不可以被放到该格点之上。那么有多少头牛可以被放到农夫约翰的电网中去呢?

INPUT FORMAT:

输入文件只有一行,包含三个用空格隔开的整数:n,m和p。

OUTPUT FORMAT:

输出文件只有一行,包含一个整数,代表能被指定的电网包含的牛的数目。


SAMPLE INPUT
7 5 10


SAMPLE OUTPUT
20


题目思路:

我用的就是很容易想到的枚举从0到max(n,p)每个部分的格点数,根据n,p的大小关系分开处理即可。
在USACO看到了皮克定理
其面积S和内部格点数目a、边上格点数目b的关系:S = a + b/2 - 1。
根据三角形面积公式求出S,如果知道了b,那么三角形内部格点数目a也就求出来了。 可以证明,一条直线((0,0),(n,m))上的格点数等于n与m的最大公约数+1, 即b=gcd(n,m)+1. gcd(n,m)为n与m的最大公约数。 代入皮克公式,即可求出a的值。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<algorithm>
#define INF 99999999
using namespace std;
FILE *fin,*fout;
int n,m,p,ans=0;

int main(){
    fin  = fopen ("fence9.in", "r");
    fout = fopen ("fence9.out", "w");
    fscanf(fin,"%d%d%d",&n,&m,&p);
    if(p>=n){
        for(int i=1;i<n;i++){
            ans+=m*i/n;
            if(m*i%n==0)ans--;      
        }
        for(int i=n;i<p;i++){
            if(i==0)continue;
            ans+=m*(p-i)/(p-n);
            if(m*(p-i)%(p-n)==0)ans--;
        }
    }else{
        for(int i=1;i<n;i++){
            ans+=m*i/n;
            if(m*i%n==0)ans--;
            if(i>=p)
            ans-=m*(i-p)/(n-p);     
        }
    }
    fprintf(fout,"%d\n",ans);
    exit(0);
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值