J.Product of GCDs
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef pair<int, int> Pii;
#define reg register
#define mp make_pair
#define pb push_back
#define Mod1(x) ((x >= Phi) && (x -= Phi))
#define Mod2(x) ((x < 0) && (x += Phi))
#define rep(i, a, b) for (int i = a, i##end = b; i <= i##end; ++i)
#define drep(i, a, b) for (int i = a, i##end = b; i >= i##end; --i)
template <class T>
inline void cmin(T& a, T b) {
((a > b) && (a = b));
}
template <class T>
inline void cmax(T& a, T b) {
((a < b) && (a = b));
}
char IO;
template <class T = int>
T rd() {
T s = 0;
int f = 0;
while (!isdigit(IO = getchar()))
f |= IO == '-';
do
s = (s << 1) + (s << 3) + (IO ^ '0');
while (isdigit(IO = getchar()));
return f ? -s : s;
}
const int N = 8e4 + 10, M = 1e7 + 30;
int n, m;
ll P, Phi;
int notpri[M + 1], pri[M / 5], pc;
ll A[N], C[N][32];
ll Calc(ll n) {
ll p = n;
for (int i = 1; 1ll * pri[i] * pri[i] <= n; ++i)
if (n % pri[i] == 0) {
p = p / pri[i] * (pri[i] - 1);
while (n % pri[i] == 0)
n /= pri[i];
}
if (n > 1)
p = p / n * (n - 1);
return p;
}
ll Mul(ll x, ll y) {
return (__int128)x * y % P;
}
ll qpow(ll x, ll k) {
ll res = 1;
for (; k; k >>= 1, x = Mul(x, x))
if (k & 1)
res = Mul(res, x);
return res;
}
int main() {
rep(i, 2, M) {
if (!notpri[i])
pri[++pc] = i;
for (int j = 1; j <= pc && 1ll * i * pri[j] <= M; ++j) {
notpri[i * pri[j]] = 1;
if (i % pri[j] == 0)
break;
}
}
rep(_, 1, rd()) {
n = rd(), m = rd(), P = rd<ll>(), Phi = Calc(P);
rep(i, 0, N - 1) A[i] = 0;
rep(i, 1, n) A[rd()]++;
rep(i, 0, n) rep(j, *C[i] = 1, min(i, m)) C[i][j] =
C[i - 1][j] + C[i - 1][j - 1],
Mod1(C[i][j]);
ll ans = 1;
rep(i, 2, N - 1) if (!notpri[i]) {
ll res = 0;
for (int x = i; x < N; x *= i) {
int c = 0;
for (int j = x; j < N; j += x)
c += A[j];
if (c < m)
break;
res += C[c][m], Mod1(res);
if (1ll * i * x >= N)
break;
}
if (res)
ans = Mul(ans, qpow(i, res));
}
printf("%lld\n", ans);
}
}
题解:别人的题解,我也看不懂就是了
K.Stack
#include <bits/stdc++.h>
#define N 1000005
#define M 4000005
using namespace std;
int n, k, b[N], a[N];
int head[N], ver[M], Next[M], tot = 0;//ver记录指向的顶点
int deg[N];//记录顶点的入度
void add(int x, int y) {//链式前向星
ver[++tot] = y;
Next[tot] = head[x];
head[x] = tot;
}
void Toposort() {//拓扑排序
queue<int> q;
int cnt = n;
for (int i = 1; i <= n; i++) {
if (!deg[i]) {
q.push(i);
}
}
while (q.size()) {
int now = q.front();
q.pop();
a[now] = cnt--;//优先给入度为0的顶点数字越大
for (int i = head[now]; i; i = Next[i]) {
int y = ver[i];
deg[y]--;
if (deg[y] == 0) {
q.push(y);
}
}
}
}
int main() {
cin >> n >> k;
for (int i = 1; i <= k; i++) {
int p, x;
cin >> p >> x;
b[p] = x;
}
stack<int> stk; //栈中存放的是一系列位置,add里面也是下标指向
bool ok = 1;
for (int i = 1; i <= n; i++) {
// cout << i << endl;
if (b[i]) {
if (stk.size() + 1 < b[i]) {
ok = 0;
break;
} else if (stk.size() + 1 == b[i]) {
if (i != 1) {
add(i, stk.top()); // a[i]比栈顶对应位置的元素大
deg[stk.top()]++;
}
stk.push(i);
} else {
while (stk.size() + 1 > b[i] && stk.size()) {
int now = stk.top();
stk.pop();
add(now, i);
deg[i]++;
}
if (stk.size()) {
add(i, stk.top());
deg[stk.top()]++;
}
stk.push(i);
}
} else {
if (i != 1) {
add(i, stk.top()); // a[i]比栈顶对应位置的元素大
deg[stk.top()]++;
}
stk.push(i);
}
}
if (!ok) {
cout << -1;
return 0;
} else {
Toposort();
for (int i = 1; i <= n; i++) {
cout << a[i] << " ";
}
}
return 0;
}
题解:正解就是通过b数组以及题目描述,构建b数组对应位置的a数组的元素的相对关系,然后拓扑排序分配编号即可。首先需要找到一种补全b数组的方法(当然不用真的补全),而要求b[i]<= i,因此令缺失部分的b[i] = b[i - 1] + 1即可满足要求(贪心)。然后i = 1 ~ n遍历每个位置同时模拟单调栈的过程,注意和题目说的不同的是栈中存放的是一个个下标(因为本身要构造的就是a序列,同时b序列已补全,实际上存储的就是a序列的对应下标了,这样可以求出来a序列各个位置之间的数的大小关系)。遍历到一个位置时如果这个位置的b[i]没有初始值,说明在这个位置执行的是入栈操作,把i入栈,这个位置的数大于栈顶那个位置对应的数;如果b[i]有初始值,若栈的大小+1比b[i]小说明无解,如果栈的大小+1等于b[i]则把i直接入栈,这个位置的数大于栈顶那个位置对应的数,若栈的大小比b[i]大则不断弹出栈顶元素并指明栈顶元素对应位置的数大于i这个位置对应的数,最后指明i这个位置的数大于栈顶元素位置对应的数并把i入栈。这样就可以得到一系列的a[i]> a[j]这样的关系(由i指向j的有向边)构成的关系图(显然为DAG),直接跑拓扑排序分配a[i]即可。
转载于