您的位置:首页 > 其它

【BZOJ3884】上帝与集合的正确用法

2018-03-22 20:28 483 查看
【题目链接】
点击打开链接

【思路要点】
欧拉拓展定理:\(a^{\phi(n)}\equiv a^{2\phi(n)}(Mod\ n)\)。
而\(\phi(\phi(n))<\frac{n}{2}\)(\(\phi(奇数)=偶数\),\(\phi(偶数)≤\frac{偶数}{2}\)),所以至多有\(O(LogP)\)个不同的模数,模数就会变成1,然后直接用欧拉定理计算即可。
时间复杂度\(O(T*(Log^2P+\sqrt{P}))\)。
【代码】
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 100005;
template <typename T> void chkmax(T &x, T y) {x = max(x, y); }
template <typename T> void chkmin(T &x, T y) {x = min(x, y); }
template <typename T> void read(T &x) {
x = 0; int f = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
x *= f;
}
template <typename T> void write(T x) {
if (x < 0) x = -x, putchar('-');
if (x > 9) write(x / 10);
putchar(x % 10 + '0');
}
template <typename T> void writeln(T x) {
write(x);
puts("");
}
int power(int x, int y, int P, bool &flg) {
if (y == 0) return 1;
int tmp = power(x, y / 2, P, flg);
if (1ll * tmp * tmp >= P) flg = true;
tmp = 1ll * tmp * tmp % P;
if (y % 2 == 0) return tmp;
else {
if (1ll * x * tmp >= P) flg = true;
return 1ll * x * tmp % P;
}
}
int phi(int x) {
int ans = x, tmp = x, now = 2;
while (now * now <= tmp) {
if (tmp % now == 0) {
ans = ans / now * (now - 1);
while (tmp % now == 0) tmp /= now;
}
now++;
}
if (tmp != 1) ans = ans / tmp * (tmp - 1);
return ans;
}
int tot, p[MAXN];
int main() {
int T; read(T);
while (T--) {
read(p[tot = 1]);
while (p[tot] != 1) {
p[tot + 1] = phi(p[tot]);
tot++;
}
int now = 2;
for (int i = tot; i >= 1; i--) {
bool flg = false;
now = power(2, now, p[i], flg);
if (flg) now += p[i];
}
writeln(now % p[1]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: