题目 | Counting Arrays
Educational Codeforces Round 138 (Rated for Div. 2)
D. Counting Arrays
https://codeforces.com/contest/1749/problem/D
2 seconds / 512 megabytes
standard input / standard output
Problem
Consider an array
An array
is a removal sequence: when you remove the -st element of the array, the condition holds, and the array becomes ; when you remove the -st element again, the condition holds, and the array becomes empty. is not a removal sequence: when you try to remove the -nd element, the condition is false.
An array is ambiguous if it has at least two removal sequences. For example, the array
You are given two integers n and m. You have to calculate the number of ambiguous arrays
Input
The only line of the input contains two integers
Output
Print one integer — the number of ambiguous arrays
Examples
Input | Output |
---|---|
2 3 | 6 |
4 2 | 26 |
4 6 | 1494 |
1337 424242424242 | 119112628 |
题解
为下文表述简单,我们称 ambiguous arrays 为多义数列,非多义数列称为单义数列,removal sequences 为消去序列。
多义数列
一个数列,要么是单义,要么是多义,因此可得上述等式。
单义数列的限制条件明显比多义数列严格,因此其数目更容易求得,所以我们反向求解。
其中总数列的数目更简单,即为:
单义数列的消去序列全为
对于任意正整数
单义数列只有一个消去序列,因此其一定全为
单义数列的限制条件:
单义数列不可有其他的消去序列,因此在整个消去过程当中,所有数都要满足
单义数列的唯一消去序列全为
结合上述两个条件,得到:数列中第
这个条件再进一步简化可以得到:数列中第
单义数列的数目:
不妨令单义数列长度为
第一位可选的数为
第二位可选的数为
第三位可选的数为
综上,长度为
长度
若像上面这么算,时间复杂度
代码
- 代码中使用线性筛法生成质数表,时间复杂度
. - 请注意代码中每一个取模的地点,漏掉的话,很有可能出现溢出问题(尤其是 cout 输出时取模)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MOD = 998244353, MAXN = 3e5 + 10;
bool not_prime[MAXN];
int prime[MAXN], idx;
void init_prime()
{
not_prime[0] = not_prime[1] = true;
for (int i = 2; i < MAXN; i++)
{
if (!not_prime[i])
prime[idx++] = i;
for (int j = 0; j < idx && prime[j] * i < MAXN; j++)
{
not_prime[prime[j] * i] = true;
if (!(i % prime[j]))
break;
}
}
}
int main()
{
init_prime();
ll n, m;
cin >> n >> m;
ll ans = 0, cnt = 1, prime_mul = 1;
for (ll i = 1; i <= n; i++)
{
if (!not_prime[i])
prime_mul *= i;
if (prime_mul > m)
break;
cnt = cnt * (m / prime_mul % MOD) % MOD;
ans = (ans + cnt) % MOD;
}
ll all = 0, pow_m = 1;
for (ll i = 1; i <= n; i++)
{
pow_m = pow_m * (m % MOD) % MOD;
all = (all + pow_m) % MOD;
}
cout << (all - ans + MOD) % MOD << endl;
return 0;
}
本文采用 CC BY-SA 4.0 许可,本文 Markdown 源码:Haotian-BiJi