2022 杭电多校(2) 补题 2, 9, 12 , 8

2 C++ to Python 水题

签到,只要无视字母、下划线、冒号后输出即可

9 ShuanQ 逆元

题意:
已知
M是质数,\(P × Q ≡ 1\,\,\, mod\, M\)
加密公式:
\(encrypted_{data} = raw_{data} \times P \mod M\)
解密公式:
\(raw_{data} = encrypted_{data} \times Q \mod M\)

给P和Q以及\(encrypted_{data}\),求加密前的原始数据\(row_{data}\)
题解:

\(P × Q ≡ 1\,\,\, mod\, M\)

可得\(P × Q − 1 = k × M, k ≥ 1\)
证明
即:M是kM的一个比P,Q大的质因子。

而且显然最多只有一个质因子满足要求。
问题就变成了求解\(min(P,Q)\)\(P × Q − 1\)的一个质因子M
求出m后,按照题目给的公式正常计算即可。
代码:

#include <iostream>
#include <cstring>
#include <vector>
#include <bits/stdc++.h>
#define endl '\n'
//#pragma GCC optimize(3)
#define int long long
#define pii pair<int, int>
using namespace std;
const int N = 1e6 + 10;

int getmaxprime(int n)
{
    for (int i = 2; i <= sqrt(1.0 * n); i++)
    {
        while (n % i == 0)
            n = n / i;
    }
    return n;
}
int p, q, e;
void solve()
{

    cin >> p >> q >> e;
    int m = getmaxprime(p * q - 1);
    //    cout<<k<<endl;
    if (m <= p || m <= q || m <= e)
    {
        cout << "shuanQ" << endl;
    }
    else
    {
        cout << ((e % m) * (q % m) + m) % m << endl;
    }
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin >> t;
    while (t--)
        solve();
    return 0;
}

12 Luxury cruise ship 背包 数学

题意:
Kayzin 每天会将 7 或 31 或 365 个硬币放入他的存钱罐中。
现在 Kayzin 想知道他至少需要多少天才能“准确地”(不多也不少)凑齐购买豪华游轮的钱。
如果 Kayzin 不能“完全”凑齐购买豪华游轮的钱,打印 -1。

题解:

有一个定义:
两个质数x,y可以通过\(ax+by\)(a和b是任意整数)组成大于\(x × y-x-y\)的任何一个整数。
通过这个定理可以发现:365可以由7和31这两个质数组成。

因此如果N较大,先用 365 将 N 减小到背包预处理的范围内,然后剩余的部分进行背包。

代码:

#include <iostream>
#include <cstring>
#include <vector>
#include <bits/stdc++.h>
#define endl '\n'
#define int long long
#define pii pair<int, int>
using namespace std;

int n, m, t;
string st, ans;
int x, y;
int min(int a, int b)
{
    if (a < b)
        return a;
    else
        return b;
}
int dp[600];
int a[3] = {7, 31, 365};
void solve()
{
    cin >> t;
    while (t--)
    {
        x = 0, y = 0;
        cin >> n;
        for (int i = 1; i <= 600; i++)
            dp[i] = 0x3f3f3f3f3f;
        int cnt = 0;
        int tmp = (n - 180) / 365;
        int res = n;
        if (tmp > 0)
        {
            res -= tmp * 365;
            cnt += tmp;
        }
        for (int i = 0; i < 3; i++)
        {
            for (int j = a[i]; j <= res; j++)
            {
                dp[j] = min(dp[j - a[i]] + 1, dp[j]);
            }
        }
        if (dp[res] == 0x3f3f3f3f3f)
            cout << -1 << endl;
        else
            cout << dp[res] + cnt << endl;
    }
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    solve();
    return 0;
}

8 Keyboard Warrior 哈希

题意:
给定一个操作序列 ( c , k ),若 c 为小写字符则往缓冲区添加 k 个 c c字符;若为 -则删除最后的 k 个字符。问是否存在一个时刻,给定的一个串 S 为缓冲区中字符串的一个连续子串

思路:
使用哈希算法来比较两个字符串是否相同,然后模拟过程即可。
然后哈希算法如果按照正常的哈希算法,需要注意
一次性加入 k 个字符 ch 的哈希值,通过等比数列公式可以得到为\(ch × \dfrac{p^k-1}{p-1}\),可以\(\mathcal O(1)\) 的计算。

如果按照标程,就是没有这个问题。
标程的哈希公式:\(hash[i]= hash[i-1]+ch * Base + k\)

#include <iostream>
#include <cstring>
#include <vector>
#include <bits/stdc++.h>
#define endl '\n'
#define int long long
#define pii pair<char, int>
#define ull unsigned long long
using namespace std;
const int N = 1e6 + 10;
const ull B = 131;

string s;
ull f[N];
pii stk[N];
void solve()
{

    int n, m;
    cin >> n >> m;

    cin >> s;
    s = '1' + s;
    int dif = 1;
    for (int i = 2; i <= n; i++)
        if (s[i] != s[i - 1])
            dif++;

    int be_len = 0, en_len = 0;
    for (int i = 1; i <= n && s[i] == s[1]; i++)
        be_len++;
    for (int i = n; i >= 1 && s[i] == s[n]; i--)
        en_len++;

    ull key = 0;
    for (int i = be_len + 1; i <= n - en_len;)
    {
        ull j = 1;
        while (s[i] == s[i + 1])
            ++j, ++i;
        key += s[i] * B + j;
        ++i;
    }

    int p = 0;
    int flag = 0;
    char ju;
    int num;
    while (m--)
    {
        cin >> ju >> num;
        if (num == 0)
            continue;
        if (ju == '-')
        {
            while (num && p)
            {
                if (stk[p].second > num)
                    stk[p].second -= num, num = 0;
                else
                    num -= stk[p].second, p--;
            }
        }
        else
        {
            if (p && stk[p].first == ju)
                stk[p].second += num;
            else
                stk[++p] = {ju, num};
        }
        if (p)
            f[p] = f[p - 1] + (stk[p].first * B + stk[p].second);

        if (dif == 1 && stk[p].second >= be_len)
            flag = 1;

        if (dif != 1 && p >= dif &&
            stk[p - dif + 1].first == s[1] && stk[p - dif + 1].second >= be_len &&
            stk[p].first == s[n] && stk[p].second >= en_len &&
            f[p - 1] - f[p - dif + 1] == key)
        {
            flag = 1;
        }
    }

    if (flag)
        cout << "yes" << endl;
    else
        cout << "no" << endl;
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t = 1;
    // cout << "ss" << endl;
    cin >> t;

    while (t--)
        solve();
    return 0;
}
posted @ 2022-07-29 17:19  kingwzun  阅读(46)  评论(0编辑  收藏  举报