2020 icpc 沈阳 i题 Rise of Shadows

题目链接
题意:
一天有 H H H小时,一小时有 M M M分钟。
问有多少整数分钟满足时针和分钟的夹角小于 A × 2 π H × M \dfrac{A\times 2\pi}{H\times M} H×MA×2π

很明显的可以列出不等式:
t × ( H − 1 ) ≤ A ( m o d H M ) t\times (H-1)\le A\pmod{HM} t×(H1)A(modHM)
定理1: a x ≡ b ( m o d n ) ax\equiv b\pmod{n} axb(modn)有解,则 gcd ⁡ ( a , n ) ∣ b \gcd(a,n)|b gcd(a,n)b
由此,可以推出当 gcd ⁡ ( H − 1 , H M ) ∣ K \gcd(H-1,HM)|K gcd(H1,HM)K有解。 K ≤ A K\le A KA
定理2:若 gcd ⁡ ( a , n ) \gcd(a,n) gcd(a,n)互质,则在 [ 0 , n − 1 ] [0,n-1] [0,n1] a x ≡ b ( m o d n ) ax\equiv b\pmod{n} axb(modn)有唯一解。
对等式两边同时除以 d = gcd ⁡ ( H − 1 , H M ) d=\gcd(H-1,HM) d=gcd(H1,HM): t × H − 1 d = K d ( m o d H M d ) \dfrac{t\times H-1}{d}= \dfrac{K}{d}\pmod{\dfrac{HM}{d}} dt×H1=dK(moddHM)
此时t在 [ 0 , H M d − 1 ] [0,\dfrac{HM}{d}-1] [0,dHM1]范围内有唯一解。当然这时候 K K K要满足 gcd ⁡ ( H − 1 , H M ) ∣ K \gcd(H-1,HM)|K gcd(H1,HM)K,那么就有 A d \dfrac{A}{d} dA K K K
最后,有推论3:若 gcd ⁡ ( a , n ) = d ∣ b \gcd(a,n)=d|b gcd(a,n)=db,则 a d x = b d ( m o d n d ) \dfrac{a}{d}x=\dfrac{b}{d} \pmod {\dfrac{n}{d}} dax=db(moddn)有唯一解,且 a x ≡ 1 ( m o d n ) ax \equiv 1\pmod n ax1(modn) d d d个对模 n n n不同余的解。
这推理证明过程我也没看懂,甚至不知道用在这对不对。
那么我们对于每个有解的 K K K就有 d d d个解,算是绝对值以及0,总共 2 A d + 1 2\dfrac{A}{d}+1 2dA+1 K K K有解,每个解乘以 d d d,那么答案就是:
d × ( 2 A d + 1 ) d\times(2\dfrac{A}{d}+1) d×(2dA+1)

特殊情况是 A = H M / 2 A=HM/2 A=HM/2这时对于每个 t t t都有解,答案是:
H M HM HM


#include<bits/stdc++.h>
using namespace std;
//    clock_t start, end;
//    start = clock();
//    end = clock();
//    cout << (double) (end - start) / CLOCKS_PER_SEC << endl;
//ios::sync_with_stdio(false);
#define  int long long
#define rep(i, x, y) for(int i=(x);i<=(y);++i)
#define dep(i, x, y) for(int i=(x);i>=(y);--i)
#define gcd(a, b) __gcd(a,b)
const long long mod = 1e9 + 7;
const int maxn = 1e7 + 10;

int lowbit(int x) { return x & -x; }

bool ispow(int n) { return (n & (n - 1)) == 0; }//O(1) 判断是否是 2^k(2的k次方)
int read() {
    int x = 0, f = 1;
    char c = getchar();
    while (c < '0' || c > '9') {
        if (c == '-') f = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * f;
}


signed main(){

    int h,m,a;
    cin>>h>>m>>a;
    if((double)a==((double)h*m/2.0)){
        cout<<h*m<<endl;
        return 0;
    }
    int d=gcd(h-1,h*m);
    cout<<d*(a/(d)*2+1)<<endl;
    return 0;
}
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值