您的位置:首页 > 科技 > IT业 > 如何规划设计一个网站_个人网站模板源码_新郑网络推广外包_河南郑州最新事件

如何规划设计一个网站_个人网站模板源码_新郑网络推广外包_河南郑州最新事件

2025/2/26 23:25:37 来源:https://blog.csdn.net/2301_80379979/article/details/145822584  浏览:    关键词:如何规划设计一个网站_个人网站模板源码_新郑网络推广外包_河南郑州最新事件
如何规划设计一个网站_个人网站模板源码_新郑网络推广外包_河南郑州最新事件

Discrete Logarithm is a Joke ( 2020-2021 Winter Petrozavodsk Camp, Day 5: Almost Retired Dandelion Contest (XXI Open Cup, Grand Prix of Nizhny Novgorod). )

Let’s take M = 1 0 18 + 31 M = 10^{18} + 31 M=1018+31 which is a prime number, and g = 42 g = 42 g=42 which is a primitive root modulo M M M, which means that g 1 m o d M , g 2 m o d M , … , g M − 1 m o d M g^{1} \bmod M, g^{2} \bmod M, \ldots, g^{M-1} \bmod M g1modM,g2modM,,gM1modM are all distinct integers from [ 1 ; M ) [1; M) [1;M). Let’s define a function f ( x ) f(x) f(x) as the smallest positive integer p p p such that g p ≡ x ( m o d M ) g^{p} \equiv x \pmod M gpx(modM). It is easy to see that f f f is a bijection from [ 1 ; M ) [1; M) [1;M) to [ 1 ; M ) [1; M) [1;M).

Let’s then define a sequence of numbers as follows:

  • a 0 = 960 002 411 612 632 915 a_{0} = 960\,002\,411\,612\,632\,915 a0=960002411612632915 (you can copy this number from the sample);
  • a i + 1 = f ( a i ) a_{i + 1} = f(a_{i}) ai+1=f(ai).

Given n n n, find a n a_{n} an.

Input

The only line of input contains one integer n n n ( 0 ≤ n ≤ 1 0 6 0 \le n \le 10^{6} 0n106).

Output

Print a n a_{n} an.

Examples

Input

0

Output

960002411612632915

Input

1

Output

836174947389522544

Input

300300

Output

263358264583736303

Input

1000000

Output

300

前置知识

这道题的模模数是 1 18 + 31 1 ^ {18} +31 118+31

所以可能数据范围会 > 64 位

要开 __int 128

现在介绍一下__int128的用法:

对于一个数,例如:___int128 a,这个数只支持四则运算,不支持 cin,cout,scanf,printf 等输入输出方式,下面介绍输入输出方式:

首先是快读函数

__int128 read()
{//直接在函数里面实现读字符串操作更简洁__int128 res=0;//初始结果赋值0char scan[1005];scanf("%s",scan);for(int i=0;i<strlen(scan);i++)res*=10,res+=scan[i]-'0';//实现进位return res;//返回__int128类型
}

其次是快写函数

void print(__int128 num)
{//递归调用,实现从高位向低位输出if(num>9) print(num/10);putchar(num%10+'0');
}

其次,这道题的 1 18 + 31 1 ^ {18} + 31 118+31 需要写成 1000000000000000000 + 31 1000000000000000000 + 31 1000000000000000000+31

为什么呢,因为 1 18 + 31 1 ^ {18} + 31 118+31 这种方式的写法是浮点类型,会丧失精度

所以要用 1000000000000000000 + 31 1000000000000000000 + 31 1000000000000000000+31 形式

题目描述

我们定义了一个大素数 ( M = 10^{18} + 31 ) 和一个原根 ( g = 42 ) 对模 ( M ) 来说。意味着 ( g^1 \mod M, g^2 \mod M, \ldots, g^{M-1} \mod M ) 是从区间 ([1, M)) 中的所有不同整数。

现在我们定义一个函数 ( f(x) ),其为满足 ( g^p \equiv x \pmod{M} ) 的最小正整数 ( p ),也就是说,( f(x) ) 是给定 ( x ) 时,最小的指数 ( p ) 使得 ( g^p \equiv x \pmod{M} )。

此时,函数 ( f ) 是从区间 ([1, M)) 到 ([1, M)) 的双射(即一一映射)。

接下来,给定 ( a_0 = 960002411612632915 ) 和递推关系:
[ a_{i+1} = f(a_i) ]
我们要求给定 ( n ),求出 ( a_n ) 的值。

输入格式

输入包含一个整数 ( n ) (( 0 \le n \le 10^6 )),表示要求的序列的索引。

输出格式

输出一个整数,即 ( a_n ) 的值。

示例

输入1:

0

输出1:

960002411612632915

输入2:

1

输出2:

836174947389522544

输入3:

300300

输出3:

263358264583736303

输入4:

1000000

输出4:

300

题解

问题分析

题目给定了一个大素数 ( M = 1 0 18 + 31 M = 10^{18} + 31 M=1018+31 ) 和一个原根 ( g = 42 ) 对于模 ( M ) 来说,要求我们找到给定 ( n ) 时的序列 ( a n a_n an ) 的值。序列是通过递推公式 ( a i + 1 = f ( a i ) a_{i+1} = f(a_i) ai+1=f(ai) ) 构造的,其中 ( f(x) ) 是给定 ( x ) 时,满足 ( $g^p \equiv x \pmod{M} $) 的最小正整数 ( p )。

由于 ( f(x) ) 的计算直接依赖于 ( g p m o d M g^p \mod M gpmodM ) 的性质,因此求解 ( f(x) ) 需要高效的计算。由于题目要求的 ( n ) 最大为 ( 10^6 ),因此我们需要预计算这些结果并高效查询。

解题思路
  1. 快速幂计算
    我们需要计算 ( g p m o d M g^p \mod M gpmodM ) 的值,这可以通过快速幂算法来实现。快速幂算法的时间复杂度为 ( O ( log ⁡ p ) O(\log p) O(logp) ),因此对于每次计算 ( f(x) ) 时,可以高效地进行。

  2. 序列的迭代计算
    我们可以从 ( a 1000000 a_{1000000} a1000000 ) 开始,通过递推计算出序列中的每个元素,直到计算到 ( $a_n $)。

  3. 优化方法
    由于我们需要计算的 ( n ) 可能非常大(最多 ( 10^6 )),因此我们应该使用一个数组来存储中间结果,以避免重复计算。

  4. 输出
    最终输出 ( a n a_n an ) 的值。

代码分析

以下是基于上述思路实现的代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define ll __int128
#define endl '\n'const int mod = 1000000000000000000 + 31;
const int M = 42;
const int N = 1e6 + 10;
const int X = 1e6;
ll an[N];// 快速幂函数,计算 a^b % mod
ll qpow(ll a, ll b)
{ll ans = 1;while (b){if (b & 1){ans = (ans * a) % mod;}b >>= 1;a = (a * a) % mod;}return ans;
}// 输出大数
void printed(ll num)
{if (num > 9){printed(num / 10);}putchar(num % 10 + '0');
}signed main()
{int n;cin >> n;an[X] = 300;// 从后往前计算a_ifor (int i = X; i >= 1; --i){an[i - 1] = qpow(M, an[i]);}printed(an[n]);
}
代码解析
  1. 常量定义

    • mod 定义了一个大的素数 ( M = 10^{18} + 31 )。
    • MN 分别用于定义数值范围和数组大小。
  2. 快速幂函数

    • qpow(a, b) 实现了快速幂算法,计算 ( a^b \mod \text{mod} ),时间复杂度为 ( O(\log b) )。
  3. 主函数

    • 输入 ( n ) 的值。
    • 初始化 an[X] = 300
    • 使用递推公式从 ( a_X = 300 ) 开始计算 ( a_{X-1}, a_{X-2}, \ldots, a_0 )。
    • 计算过程中使用快速幂函数 qpow 来计算幂的模。
    • 最终输出 ( a_n ) 的值。
  4. 输出函数

    • printed() 是一个递归的输出函数,用于输出大整数值。

复杂度分析

  • 时间复杂度

    • 每次计算 ( f(x) ) 时需要进行快速幂运算,时间复杂度为 ( O(\log M) ),其中 ( M ) 约为 ( 10^{18} ),因此每次快速幂的复杂度约为 ( O(60) )。
    • 整体循环进行 ( 10^6 ) 次,故总时间复杂度为 ( O(10^6 \times 60) ),即 ( O(10^6) ),能够满足题目要求。
  • 空间复杂度

    • 使用了大小为 ( 10^6 ) 的数组 an,因此空间复杂度为 ( O(10^6) )。

总结

通过快速幂算法,我们能够高效计算出序列中的每个元素,利用递推公式从后向前迭代计算序列,最终求出 ( a_n ) 的值。通过这样的优化方式,能够处理题目给定的最大输入规模。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com