给定长度为
n
n
n的数组
a
a
a,若
g
c
d
(
a
i
,
i
)
=
1
gcd(ai, i) = 1
gcd(ai,i)=1(元素与其下标互质)则可以删除
a
i
ai
ai,其后的元素顺序前移直到数组为空。将删除的元素的下标按删除顺序排成一列这就是删除序列
b
b
b。当数组
a
a
a具有两种及以上的不同删除序列时,称数组
a
a
a具有二重性。
求长度为
1
1
1~
n
n
n的数组 ,数组元素
1
<
=
a
i
<
=
m
1<=ai<=m
1<=ai<=m,有多少数组具有二重性。
首先题目询问的是长度分别为
1
,
2
,
3
,
…
…
,
n
1,2,3,……,n
1,2,3,……,n的数组,而不只是长度为
n
n
n的数组,比赛时样例的26我死活算不出来 。
因为数字
1
1
1与所有数都互质
g
c
d
(
1
,
x
)
=
1
gcd(1,x) = 1
gcd(1,x)=1 所以很容易想到所有的数组都至少有一种删除序列即
b
=
(
1
,
1
,
1
,
…
…
,
1
)
b = (1,1,1,……,1)
b=(1,1,1,……,1),所以我们只需要再找到一种删除方式就可以构造出二重性。
求二重性的个数发现有困难,但是正难则反,我们可以考虑求出所有方案
s
u
m
sum
sum - 没有二重性的数组数量
r
e
s
res
res。
开始求不具有二重性的数组数量,即我们需要构造出删除序列只有 1 1 1的数组。考虑初始数组元素 a i ai ai,要让删除序列全为 1 1 1那么不仅所有的 g c d ( a i , i ) ! = 1 gcd(ai,i) != 1 gcd(ai,i)!=1 并且在删除过程中 a i ai ai在向前移动过程中也要保持 g c d ( a i , j ) ! = 1 ( 2 < = j < = i ) gcd(ai,j) != 1 (2 <= j <= i) gcd(ai,j)!=1(2<=j<=i) ,也就是说 a i ai ai的质因数要包含 2 2 2~ i i i之间所有的质数 ,而 m m m最大为 1 0 12 10^{12} 1012最多包含十几个质因子,也就是说当数组长度大于一定以后(大概 40 40 40),就不可能有不具有二重性的数组了。
最后我们可以递推的方式求解,然后用累加的方法解决数组长度为 1 1 1~ n n n的问题。
#include
#include
using namespace std;
#define ll long long
const int N = 3e5 + 10, mod = 998244353;
ll n,m,p[50] = {0,0,2,3,0,5,0,7,0,0,0,11,0,13,0,0,0,17,0,19,0,0,0,23,0,0,0,0,0,29,0,31,0,0,0,0,0,37,41,43,47};//50以内的质数
int main()
{
cin >> n >> m;
ll sum = 0, sum1 = 1;
for(int i = 1; i <= n; i ++){
sum1 = sum1 * (m % mod) % mod;//sum1是长度为i的数组的总方案
sum = (sum + sum1) % mod;//sum是累加结果
}
ll res = m % mod, res1 = m % mod, k = 1;
for(int i = 2; i <= n; i ++){
if(p[i]){
if(k * i <= m) k = k * i;
else break;
}
res1 = res1 * (m / k % mod) % mod;//res1是长度为i的数组没有二重性的总方案
res = (res + res1) % mod;//res是累加结果
}
printf("%lld\n",(sum + mod - res) % mod);//sum - res为结果
return 0;
}
更新:
D题10.21,E题待更新。