CF1174E Ehab and the Expected GCD Problem(DP,数论)

Posted 1000suns

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF1174E Ehab and the Expected GCD Problem(DP,数论)相关的知识,希望对你有一定的参考价值。

题目大意:对于一个序列,定义它的价值是它的所有前缀和的 $\gcd$ 中互不相同的数的个数。给定整数 $n$,问在 $1$ 到 $n$ 的排列中,有多少个排列的价值达到最大值。答案对 $10^9+7$ 取模。

$2\le n\le 10^6$。


一道 Div. 2 的难度 2500 的题,真的不是吹的……

首先考虑排列的第一个数 。假如分解质因子后为 $\prod p_i^c_i$,那么此时排列价值的最大值为 $\sum c_i$。

为什么?因为如果 $\gcd$ 变了,那么一定变成原来 $\gcd$ 的约数。每次变化 $\sum c_i$ 至少 $-1$。所以最大值就是 $\sum c_i$。

首先发现,质因子 $p_i$ 中不会有 $\ge 5$ 的数。因为此时可以把 $p_i$ 变成 $2^2$,约数更多且仍然合法。

然后,设分解质因子后 $3$ 的次数为 $c$,那么 $0\le c\le 1$。因为当 $c\ge 2$ 时,可以把 $3^2$ 变成 $2^3$,约数更多且仍然合法。

所以第一个数可以被表示成 $2^x3^y$,其中 $y\in\0,1\$。

那么就能上DP了。(为什么每次都那么突然……)

设 $f[i][x][y]$ 表示目前填了前 $i$ 位,当前的 $\gcd$ 是 $2^x3^y$,的总合法序列数。

初始状态 $f[1][\lfloor\log_2n\rfloor][0]=1$。如果 $2^\lfloor\log_2n\rfloor-1\times 3\le n$,那么还有 $f[1][\lfloor\log_2n\rfloor-1][1]=1$。其它的状态无用,只有这两个状态的 $x+y$ 达到了最大值。

答案为 $f[n][0][0]$。因为排列包含 $1$,所以 $\gcd$ 一定会变为 $1$。

如何转移?(以下设 $cnt(x)=\lfloor\fracnx\rfloor$,即 $x$ 的倍数的个数)

  • $\gcd$ 不变。那么 $f[i][x][y]+=f[i-1][x][y](cnt(2^x3^y)-(i-1))$。因为新选择的数可以是且一定是 $2^x3^y$ 的倍数。然而前 $i-1$ 个位置都是 $2^x3^y$ 的倍数,所以要减掉。
  • $\gcd/2$,也就是 $x--$(此时要求 $x<\lfloor\log_2n\rfloor$)。那么 $f[i][x][y]+=f[i-1][x+1][y](cnt(2^x3^y)-cnt(2^x+13^y))$。因为新选择的数一定是 $2^x3^y$ 的倍数,但一定不是 $2^x+13^y$ 的倍数(否则 $\gcd$ 不变)。前 $i-1$ 个位置都是 $2^x+13^y$ 的倍数,所以不用减掉。
  • $\gcd/3$,也就是 $y--$(此时要求 $y=0$)。那么 $f[i][x][y]+=f[i-1][x][y+1](cnt(2^x3^y)-cnt(2^x3^y+1))$。

时间复杂度 $O(n\log n)$。

技术图片
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int maxn=1000100,mod=1000000007;
#define MP make_pair
#define PB push_back
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define ROF(i,a,b) for(int i=(a);i>=(b);i--)
#define MEM(x,v) memset(x,v,sizeof(x))
inline ll read()
    char ch=getchar();ll x=0,f=0;
    while(ch<0 || ch>9) f|=ch==-,ch=getchar();
    while(ch>=0 && ch<=9) x=x*10+ch-0,ch=getchar();
    return f?-x:x;

int n,lt,f[maxn][21][2];
inline int cnt(int x)return n/x;
int main()
    n=read();
    lt=log2(n);
    f[1][lt][0]=1;
    if((1<<(lt-1))*3<=n) f[1][lt-1][1]=1;
    FOR(i,2,n) FOR(j,0,lt)
        f[i][j][0]=(1ll*f[i-1][j][0]*(cnt(1<<j)-(i-1))+1ll*f[i-1][j+1][0]*(cnt(1<<j)-cnt(1<<(j+1)))+1ll*f[i-1][j][1]*(cnt(1<<j)-cnt((1<<j)*3)))%mod;
        f[i][j][1]=(1ll*f[i-1][j][1]*(cnt((1<<j)*3)-(i-1))+1ll*f[i-1][j+1][1]*(cnt((1<<j)*3)-cnt((1<<(j+1))*3)))%mod;
    
    printf("%d\n",f[n][0][0]);
View Code

 

以上是关于CF1174E Ehab and the Expected GCD Problem(DP,数论)的主要内容,如果未能解决你的问题,请参考以下文章

CF1174D Ehab and the Expected XOR Problem - 构造

CF.862D.Mahmoud and Ehab and the binary string(交互 二分)

cf 1174 D Ehab and the Expected XOR Problem

CF D. Ehab and the Expected XOR Problem 贪心+位运算

CF1174F Ehab and the Big Finale

[CF959E] Mahmoud and Ehab and the xor-MST - 贪心,最小生成树