【难度】
2
/
10
2/10
2/10
分段打表简单题
(或者很难得矩阵快速幂)
【题意】
求
f
(
n
)
f(n)
f(n),其中
{
f
(
0
)
=
0
f
(
n
)
=
g
(
n
,
f
(
n
−
1
)
)
其
中
g
(
x
,
y
)
=
(
(
y
−
1
)
x
5
+
x
3
–
x
y
+
3
x
+
7
y
)
%
9973
\begin{cases} f(0) = 0 \\ f(n) = g(n, f(n-1))\\ \end{cases}\\ 其中\quad g(x,y) = ((y-1)x^5 + x^3 – xy + 3x + 7y)\ \% \ 9973
{f(0)=0f(n)=g(n,f(n−1))其中g(x,y)=((y−1)x5+x3–xy+3x+7y) % 9973
【数据范围】
1 ≤ n ≤ 1 0 8 1\le n\le 10^8 1≤n≤108
限时500ms
【输入样例】
50
【输出样例】
6300
【思路】
式子很奇怪,时间要求很短,我们第一反应就是打表。
但是数据范围很大。冒着好奇心,我普通打了一下表,结果txt直接500mb
(对的,没法直接打表)
但是我们可以分段打表!
答案记录
1
0
8
10^8
108 个不行,我们大不了只记录 100 个,第
i
i
i 个答案代表:
a
n
s
[
i
]
=
f
[
i
∗
1000000
]
ans[\ i\ ] = f[\ i\ *\ 1000000\ ]
ans[ i ]=f[ i ∗ 1000000 ]
然后我们从这个记录点开始从前往后递推出
f
[
n
]
f[n]
f[n] 答案。
那么,我们对于每次查询,我们最多需要进行1000000次递推计算即可。
(因为只有一次查询,所以时间复杂度很可以)。
【核心代码】
时间复杂度
O
(
1
0
6
)
O(10^6)
O(106)
注:
1
0
8
10^8
108 大约1000ms,所以
1
0
6
10^6
106 大约10ms , 但是操作取模特别多,常数大。
T i m e ( m s ) 156 Time(ms)156 Time(ms)156
注:当然打表1000个数也可以,无所谓啦。
const ll MOD = 998244353;
ll f[]={}; \\\ 这个自己打表一下即可呀
int main()
{
///fout; /// 打表时文件输出
f[0] = 0;
int n;cin >> n;
ll be = f[n/1000000];
ll now = f[n/1000000];
for(ll i=n/1000000*1000000 + 1;i<=n;++i){
ll n3 = i%MOD*i%MOD*i%MOD;
ll n5 = n3*i%MOD*i%MOD;
now = 0LL;
now += (be-1)*n5%MOD;
now%=MOD;
now += n3 + 3*i + 7*be;
now%=MOD;
now = (now - i * be)%MOD;
now += MOD;
now%=MOD;
be = now;
}
cout << now;
return 0;
}