• [BZOJ 3884]上帝与集合的正确用法


    Description

    根据一些书上的记载,上帝的一次失败的创世经历是这样的:
    第一天, 上帝创造了一个世界的基本元素,称做“元”。
    第二天, 上帝创造了一个新的元素,称作“α”。“α”被定义为“元”构成的集合。容易发现,一共有两种不同的“α”。
    第三天, 上帝又创造了一个新的元素,称作“β”。“β”被定义为“α”构成的集合。容易发现,一共有四种不同的“β”。
    第四天, 上帝创造了新的元素“γ”,“γ”被定义为“β”的集合。显然,一共会有16种不同的“γ”。
    如果按照这样下去,上帝创造的第四种元素将会有65536种,第五种元素将会有2^65536种。这将会是一个天文数字。
    然而,上帝并没有预料到元素种类数的增长是如此的迅速。他想要让世界的元素丰富起来,因此,日复一日,年复一年,他重复地创造着新的元素……
    然而不久,当上帝创造出最后一种元素“θ”时,他发现这世界的元素实在是太多了,以致于世界的容量不足,无法承受。因此在这一天,上帝毁灭了世界。
    至今,上帝仍记得那次失败的创世经历,现在他想问问你,他最后一次创造的元素“θ”一共有多少种?
    上帝觉得这个数字可能过于巨大而无法表示出来,因此你只需要回答这个数对p取模后的值即可。
    你可以认为上帝从“α”到“θ”一共创造了10^9次元素,或10^18次,或者干脆∞次。
    一句话题意:

    Input

    接下来T行,每行一个正整数p,代表你需要取模的值

    Output

    T行,每行一个正整数,为答案对p取模后的值

    Sample Input

    3
    2
    3
    6

    Sample Output

    0
    1
    4

    HINT

    对于100%的数据,T<=1000,p<=10^7

    题解

    用扩展欧拉定理(降幂大 Fa♂):$$a^q equiv a^{q mod varphi(m)+varphi(m)} pmod{m}$$

    其中,$a,m in mathbb{Z}^*$

    $$2^{2^{2^{2^{2^{2^{cdots}}}}}} equiv 2^{2^{2^{2^{2^{2^{cdots}mod ~varphi(varphi(varphi(varphi(varphi(p)))))+varphi(varphi(varphi(varphi(varphi(p)))))}mod ~varphi(varphi(varphi(varphi(p))))+varphi(varphi(varphi(varphi(p))))}mod ~varphi(varphi(varphi(p)))+varphi(varphi(varphi(p)))}mod ~varphi(varphi(p))+varphi(varphi(p))}mod ~varphi(p)+varphi(p)} pmod{p}$$

    显然当上述式子递归到一定层数后 $varphi$ 值变成 $1$ 或 $2$ 则 $mod~varphi$ 的值为 $0$ 就不用递归下去了。

     1 //It is made by Awson on 2018.1.13
     2 #include <set>
     3 #include <map>
     4 #include <cmath>
     5 #include <ctime>
     6 #include <queue>
     7 #include <stack>
     8 #include <cstdio>
     9 #include <string>
    10 #include <vector>
    11 #include <cstdlib>
    12 #include <cstring>
    13 #include <iostream>
    14 #include <algorithm>
    15 #define LL long long
    16 #define Max(a, b) ((a) > (b) ? (a) : (b))
    17 #define Min(a, b) ((a) < (b) ? (a) : (b))
    18 #define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b))
    19 using namespace std;
    20 const int N = 1e7;
    21 const int MOD = 100003;
    22 void read(int &x) {
    23     char ch; bool flag = 0;
    24     for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar());
    25     for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar());
    26     x *= 1-2*flag;
    27 }
    28 void write(int x) {
    29     if (x > 9) write(x/10);
    30     putchar(x%10+48);
    31 }
    32 
    33 int t, p, prime[N+5], tot, phi[N+5];
    34 
    35 void get_phi() {
    36     phi[1] = 1;
    37     for (int i = 2; i <= N; i++) {
    38     if (!phi[i]) phi[i] = i-1, prime[++tot] = i;
    39     for (int j = 1; j <= tot && i*prime[j] <= N; j++) {
    40         if (!(i%prime[j])) {phi[i*prime[j]] = prime[j]*phi[i]; break; }
    41         else phi[i*prime[j]] = phi[i]*phi[prime[j]];
    42     }
    43     }
    44 }
    45 int quick_pow(int a, int b, int p) {
    46     int ans = 1;
    47     while (b) {
    48     if (b&1) ans = (LL)ans*a%p;
    49     a = (LL)a*a%p, b >>= 1;
    50     }
    51     return ans;
    52 }
    53 int f(int p) {
    54     if (phi[p] <= 2) return quick_pow(2, phi[p], p);
    55     return quick_pow(2, f(phi[p])+phi[p], p);
    56 }
    57 void work() {
    58     get_phi(); read(t);
    59     while (t--) read(p), write(quick_pow(2, f(phi[p])+phi[p], p)), putchar('
    ');
    60 }
    61 int main() {
    62     work();
    63     return 0;
    64 }
  • 相关阅读:
    这样的程序员创业有戏
    一个29岁总裁对大学生的16条忠告
    向C#的String类添加按字节截取字符串的扩展方法
    妙用SQL Server聚合函数和子查询迭代求和
    为什么要在定义抽象类时使用abstract关键字
    C# 抽象类
    C# 虚函数和重载函数
    在指定文本里记录内容
    静态和非静态方法
    抽象类
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/8279171.html
Copyright © 2020-2023  润新知