2019 ACM-ICPC North America Qualification Contest B Diagonal Cut

题意

给一个由 m ∗ n m*n mn 1 ∗ 1 1*1 11的小矩形组成的长为m,宽为n的大矩形,连接其一条对角线,求被对角线一分为二的小矩形的个数

思路

img

首先画个图,对角线方程为 y = N M y=\frac{N}{M} y=MN,设正方形左下角点坐标为 ( p , q ) (p,q) pq,则正方形中心 ( p + 1 2 , q + 1 2 ) (p+\frac{1}{2},q+\frac{1}{2}) p+21,q+21,当对角线过正方形中心时,正方形面积被分为两个相等的部分,由此可列出方程:

( p + 1 2 ) ∗ N M = q + 1 2 ( 0 < = p < M , 0 < = q < N ) (p+\frac{1}{2})*\frac{N}{M}=q+\frac{1}{2}(0<=p<M,0<=q<N) (p+21)MN=q+210<=p<M,0<=q<N 求p,q解的组数

其中N可写为 n ∗ g c d ( M , N ) n*gcd(M,N) ngcd(M,N),同理M可写为 m ∗ g c d ( M , N ) m*gcd(M,N) mgcd(M,N)

方程可化为:

( 2 p + 1 ) ∗ n m = 2 q + 1 ( 0 < = p < M , 0 < = q < N ) (2p+1)*\frac{n}{m}=2q+1(0<=p<M,0<=q<N) (2p+1)mn=2q+10<=p<M0<=q<N

显然 2 p + 1 2p+1 2p+1 2 q + 1 2q+1 2q+1为奇数,所以m,n均为奇数时才有解,解释如下:

(1)若n为奇,m为偶 ( 2 p + 1 ) ∗ n m (2p+1)*\frac{n}{m} (2p+1)mn必为小数, 2 q + 1 2q+1 2q+1为整数,无解;

(2))若n为奇,m为奇 ( 2 p + 1 ) ∗ n m (2p+1)*\frac{n}{m} (2p+1)mn可能为整数, 2 q + 1 2q+1 2q+1为整数,可能有解;

(3)若n为偶,m为偶 ( 2 p + 1 ) ∗ n m (2p+1)*\frac{n}{m} (2p+1)mn必为小数, 2 q + 1 2q+1 2q+1为整数,无解;

(4)若n为偶,m为奇 ( 2 p + 1 ) ∗ n m (2p+1)*\frac{n}{m} (2p+1)mn若为整数,则是偶数, 2 q + 1 2q+1 2q+1为奇数,无解;

方程再化为

2 p + 1 m = 2 q + 1 n ( 1 < = 2 p + 1 < 2 M + 1 , 1 < = 2 q + 1 < 2 N + 1 ) \frac{2p+1}{m}=\frac{2q+1}{n}(1<=2p+1<2M+1,1<=2q+1<2N+1) m2p+1=n2q+11<=2p+1<2M+11<=2q+1<2N+1

( 1 < = 2 p + 1 < 2 M + 1 , 1 < = 2 q + 1 < 2 N + 1 ) (1<=2p+1<2M+1,1<=2q+1<2N+1) 1<=2p+1<2M+11<=2q+1<2N+1可改写为 ( m < = 2 p + 1 < = 2 m g c d ( M , N ) , n < = 2 q + 1 < = 2 n g c d ( M , N ) ) (m<=2p+1<=2mgcd(M,N),n<=2q+1<=2ngcd(M,N)) m<=2p+1<=2mgcd(M,N)n<=2q+1<=2ngcd(M,N)
方程解如下:

pq
( m − 1 ) / 2 (m-1)/2 (m1)/2 ( n − 1 ) / 2 (n-1)/2 (n1)/2
( 3 m − 1 ) / 2 (3m-1)/2 (3m1)/2 ( 3 n − 1 ) / 2 (3n-1)/2 (3n1)/2
( 5 m − 1 ) / 2 (5m-1)/2 (5m1)/2 ( 5 n − 1 ) / 2 (5n-1)/2 (5n1)/2
( 2 g c d ( M , N ) − 1 ) ∗ m − 1 ) / 2 (2gcd(M,N)-1)*m-1)/2 (2gcd(M,N)1)m1)/2 ( ( 2 g c d ( M , N ) − 1 ) ∗ n − 1 ) / 2 ((2gcd(M,N)-1)*n-1)/2 ((2gcd(M,N)1)n1)/2
endend

一共 g c d ( M , N ) gcd(M,N) gcd(M,N)个解

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll gcd(ll m,ll n)
{
    ll a=m,b=n;
    if(n>m)
    {
        swap(m,n);
    }
    while(m%n)
    {
        ll k=n;
        n=m%n;
        m=k;
    }
    a/=n;
    b/=n;
    return (a&1&&b&1)?n:0;
}

int main()
{
    ll m,n;
    cin>>m>>n;
    ll g=gcd(m,n);
    cout<<g<<endl;
    return 0;
}
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值