HDU 3223 Decrypt Messages 【N次剩余+模拟】

题目链接

题意: xqmodp=a ,已知 p,q,a ,求从2000.01.01 00:00:00过了 x <script type="math/tex" id="MathJax-Element-203">x</script>秒后是几年几月几日几时几分几秒。要列出所有的可能情况。如果年份模10等于5或8,则这一年的最后一天会多一秒。(+1s)

求N次剩余,然后模拟出时间…… 不知道为什么,T到死…… 调了调又换了个板子才过……

辣鸡模板……毁我青春……

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <cmath>
#include <vector>
#include <queue>
#include <set>
#include <map>
using namespace std;

typedef long long ll;
typedef long long LL;

int kase = 0;

bool isleap(int yy) {
    if (yy % 400 == 0) {
        return true;
    }
    else if (yy % 4 == 0) {
        if (yy % 100 != 0)
            return true;
    }
    return false;
}

ll calyear(int yy) {
    // 31536000
    // 31622400 leap year
    // 31536001 leap second
    ll res = 31536000;
    if (isleap(yy))
        res += 86400;
    if (yy % 10 == 5 || yy % 10 == 8)
        res++;
    return res;
}

ll calmonth(int yy, int mm) {
    if (mm == 2) {
        if (isleap(yy)) {
            return 29 * 86400;
        }
        else
            return 28 * 86400;
    }
    if (mm == 12) {
        if (yy % 10 == 5 || yy % 10 == 8) {
            return 31 * 86400 + 1;
        }
        else
            return 31 * 86400;
    }
    if (mm == 1 || mm == 3 || mm == 5 || mm == 7 || mm == 8 || mm == 10) {
        return 31 * 86400;
    }
    return 30 * 86400;
}

LL extgcd(LL a, LL b, LL &x, LL &y) {
    if (0 == b) {
        x = 1;
        y = 0;
        return a;
    } else {
        int r = extgcd(b, a % b, y, x);
        y -= x * (a / b);
        return r;
    }
}

LL pow_mod(LL x, LL k, LL m) {
    LL r = 1 % m;
    while (k) {
        if (1 & k)r = ((r * x) % m + m) % m;
        x = ((x * x) % m + m) % m;
        k >>= 1;
    }
    return r;
}

int g_test(LL g, LL p, vector<LL> &v) {
    LL sz = v.size();
    for (LL i = 0; i < sz; i++)
        if (1 == pow_mod(g, (p - 1) / v[i], p))
            return 0;
    return 1;
}

LL primitive_rt(LL p) {
    LL t = p - 1;
    std::vector<LL> v;
    for (LL i = 2; i <= t / i; i++)
        if (0 == t % i) {
            v.push_back(i);
            while (0 == t % i)
                t /= i;
        }
    if (1 != t)
        v.push_back(t);
    LL g = 1;
    while (true) {
        if (g_test(g, p, v))
            return g;
        g++;
    }
}

LL discrete_log(LL x, LL n, LL m) {
    // x^y = n (mod m)
    map< LL, LL > rec;
    LL s = (LL)sqrt((double)m);
    while (s * s <= m)s++;
    LL cur = 1;
    for (LL i = 0; i < s; i++) {
        rec[cur] = i;
        cur = ((cur * x) % m + m) % m;
    }
    LL mul = cur;
    cur = 1;
    for (LL i = 0; i < s; i++) {
        LL more = (n * pow_mod(cur, m - 2, m) % m + m) % m;
        if (rec.count(more))
            return i * s + rec[more];
        cur = ((cur * mul) % m + m) % m;
    }
    return -1;
}

// x ^ N = a (mod p)
vector<LL> n_residue(LL N, LL a, LL p) {
    vector<LL> res;
    LL g = primitive_rt(p);
    LL m = discrete_log(g, a, p);
    if (0 == a) {
        res.push_back(0);
        return res;
    }
    if (-1 == m) {
        return res;
    }
    LL A = N, B = p - 1, C = m, x, y;
    LL d = extgcd(A, B, x, y);
    if (0 != C % d) {
        return res;
    }
    x = x * (C / d) % B;
    LL delta = B / d;
    for (LL i = 0; i < d; i++) {
        x = ((x + delta) % B + B) % B;
        res.push_back(pow_mod(g, x, p));
    }
    sort(res.begin(), res.end());
    res.erase(unique(res.begin(), res.end()), res.end());
    return res;
}

int main() {
    // freopen("1.txt","r",stdin);
    int T;
    scanf("%d", &T);
    getchar();
    while (T--) {
        ll p, q, a;
        scanf("%lld %lld %lld", &p, &q, &a);
        // cout<<p<<" "<<q<<" "<<a<<endl;
        vector <ll> vec = n_residue(q, a, p);
        if (vec.size() == 0) {
            printf("Case #%d:\n", ++kase);
            printf("Transmission error\n");
            continue;
        }
        printf("Case #%d:\n", ++kase);
        for (int i = 0; i < vec.size(); i++) {
            int yy = 2000, mm = 1, dd = 1, hour = 0, min = 0, sec = 0;
            ll x = vec[i];
            while (x >= calyear(yy)) {
                x -= calyear(yy);
                yy++;
            }
            while (x >= calmonth(yy, mm)) {
                x -= calmonth(yy, mm);
                mm++;
            }
            int cha;
            if ((yy % 10 == 5 || yy % 10 == 8) && mm == 12 && dd == 31) {
                cha = 86401;
            }
            else {
                cha = 86400;
            }
            while (x >= cha) {
                x -= cha;
                dd++;
                if ((yy % 10 == 5 || yy % 10 == 8) && mm == 12 && dd == 31) {
                    cha = 86401;
                }
                else {
                    cha = 86400;
                }
            }
            hour = x / 3600;
            min = x % 3600 / 60;
            sec = x % 60;
            if (hour == 24) {
                hour = 23;
                min = 59;
                sec = 60;
            }
            printf("%04d.%02d.%02d %02d:%02d:%02d\n", yy, mm, dd, hour, min, sec);
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值