题目 | 新取模运算
2023 年华中科技大学程序设计竞赛新生赛
F - 新取模运算
https://www.luogu.com.cn/problem/P9774?contestId=138479
题目
在这道题中,我们定义一个新的运算符号
当计算
给定一个质数
输入
第一行包含两个整数
接下来
输出
对于每次询问,输出一行包含一个整数,即
样例
样例输入 #1
3 7
11
45
14
样例输出 #1
4
1
2
样例输入 #2
2 10007
1919
810
样例输出 #2
3152
3679
题解
根据取模的性质:
那么对于
模 | 模 | 模 | |
---|---|---|---|
其中,
我们分块来考虑:
除最左侧一列外的剩余部分
- 除最下面一行外的剩余部分:
- 最下面的一行:
- 除最下面一行外的剩余部分:
最左侧的一列
- 将
除掉后剩余内容为 ,递归进行计算。
- 将
预处理出
代码
#include <bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;
constexpr int MAXN = 1e6 + 10;
int fact[MAXN];
int n, p;
int bpow(int a, int b)
{
a %= p;
int ans = 1;
while (b)
{
if (b % 2)
ans = ans * a % p;
a = a * a % p;
b /= 2;
}
return ans;
}
void init_fact()
{
fact[0] = fact[1] = 1;
for (int i = 2; i < p; i++)
fact[i] = fact[i - 1] * i % p;
}
int calc(int n)
{
if (n == 0)
return 1;
int ans = bpow(fact[p - 1], n / p) * fact[n % p] % p;
return calc(n / p) * ans % p;
}
void solve()
{
cin >> n;
cout << calc(n) << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t = 1;
cin >> t >> p;
init_fact();
while (t--)
solve();
return 0;
}
本文采用 CC BY-SA 4.0 许可,本文 Markdown 源码:Haotian-BiJi