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$。
那么排列的价值达到最大值,只有在第一个数的 $\sum c_i$ 达到最大值才可能,并且每次 $\gcd$ 变化只会令 $\sum c_i$ 减小 $1$。
首先发现,质因子 $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\frac{n}{x}\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+1}3^y))$。因为新选择的数一定是 $2^x3^y$ 的倍数,但一定不是 $2^{x+1}3^y$ 的倍数(否则 $\gcd$ 不变)。前 $i-1$ 个位置都是 $2^{x+1}3^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=,mod=;
#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=,f=;
while(ch<'' || ch>'') f|=ch=='-',ch=getchar();
while(ch>='' && ch<='') x=x*+ch-'',ch=getchar();
return f?-x:x;
}
int n,lt,f[maxn][][];
inline int cnt(int x){return n/x;}
int main(){
n=read();
lt=log2(n);
f[][lt][]=;
if((<<(lt-))*<=n) f[][lt-][]=;
FOR(i,,n) FOR(j,,lt){
f[i][j][]=(1ll*f[i-][j][]*(cnt(<<j)-(i-))+1ll*f[i-][j+][]*(cnt(<<j)-cnt(<<(j+)))+1ll*f[i-][j][]*(cnt(<<j)-cnt((<<j)*)))%mod;
f[i][j][]=(1ll*f[i-][j][]*(cnt((<<j)*)-(i-))+1ll*f[i-][j+][]*(cnt((<<j)*)-cnt((<<(j+))*)))%mod;
}
printf("%d\n",f[n][][]);
}
CF1174E Ehab and the Expected GCD Problem(DP,数论)的更多相关文章
- CF1174E Ehab and the Expected GCD Problem(动规+数论+分解)
做法 先来填第一个数,为了保证\(f(p)\)最大,第一个数分解一下为\(\prod\limits_{p_i}p_i^{k_i}\)使得\(\sum\limits_{k_i}\)最大 显然第一个数为\ ...
- Codeforces Round #563 (Div. 2) E. Ehab and the Expected GCD Problem
https://codeforces.com/contest/1174/problem/E dp 好题 *(if 满足条件) 满足条件 *1 不满足条件 *0 ///这代码虽然写着方便,但是常数有点大 ...
- codeforces#1157D. Ehab and the Expected XOR Problem(构造)
题目链接: http://codeforces.com/contest/1174/problem/D 题意: 构造一个序列,满足以下条件 他的所有子段的异或值不等于$x$ $1 \le a_i< ...
- 【CF1174D】 Ehab and the Expected XOR Problem - 构造
题面 Given two integers \(n\) and \(x\), construct an array that satisfies the following conditions: · ...
- CF1174D Ehab and the Expected XOR Problem
思路: 使用前缀和技巧进行问题转化:原数组的任意子串的异或值不能等于0或x,可以转化成前缀异或数组的任意两个元素的异或值不能等于0或x. 实现: #include <bits/stdc++.h& ...
- CF1174D Ehab and the Expected XOR Problem(二进制)
做法 求出答案序列的异或前缀和\(sum_i\),\([l,r]\)子段异或和可表示为\(sum_r\bigoplus sum_{l-1}\) 故转换问题为,填\(sum\)数组,数组内的元素不为\( ...
- CF D. Ehab and the Expected XOR Problem 贪心+位运算
题中只有两个条件:任意区间异或值不等于0或m. 如果只考虑区间异或值不等于 0,则任意两个前缀异或值不能相等. 而除了不能相等之外,还需保证不能出现任意两个前缀异或值不等于m. 即 $xor[i]$^ ...
- Codeforces 798C - Mike and gcd problem(贪心+数论)
题目链接:http://codeforces.com/problemset/problem/798/C 题意:给你n个数,a1,a2,....an.要使得gcd(a1,a2,....an)>1, ...
- Codeforces 1088E Ehab and a component choosing problem
Ehab and a component choosing problem 如果有多个连接件那么这几个连接件一定是一样大的, 所以我们先找到值最大的连通块这个肯定是分数的答案. dp[ i ]表示对于 ...
随机推荐
- 2018 ACM-ICPC徐州站网络赛 G题
There's a beach in the first quadrant. And from time to time, there are sea waves. A wave ( xxx , yy ...
- javascript去除字符串中的空格
使用JavaScript去除字符串的空格,可以有两种方法,一种是使用replace()方法将空格(空白符)替换为空串,一种就是使用trim()方法去除字符串两端的空白字符. replace()方法 r ...
- Linux常用命令:fdisk mkfs mount umount fstab实现自动挂载
写在前 记录点常用命令,fdisk mkfs mount和umount,以及fstab实现自动挂载 fdisk fdisk主要用于操作硬盘的分区表.分区,下面简单记一点最常用的部分 查看当前系统识别到 ...
- Docker入门之安装与简单使用操作
1.docker安装 #1.检查内核版本,必须是3.10及以上 uname -r #2.安装 yum -y install docker 2.docker简单使用 #1.启动docker system ...
- pod的yaml例子
apiVersion: apps/v1beta2 kind: Deployment metadata: name: nginx-deployment spec: replicas: 3 selecto ...
- Mysql序列(七)—— order by优化
前言 在mysql中满足order by的处理方式有两种: 让索引满足排序,即扫描有序索引然后再找到对应的行结果,这样结果即是有序: 使用索引查询出结果或者扫描表得到结果然后使用filesort排序: ...
- HTTP STATUS 400 – BAD REQUEST ,SPRINGMVC错误
400大多为前台传的数据于后台接受数据不符合,注意Date数据类型最容易错. 然后需要调用实体类的空参构造方法,,注意创建了有参构造方法后,创建一个空参构造方法.
- 2019 上海轻轻java面试笔试题 (含面试题解析)
本人5年开发经验.18年年底开始跑路找工作,在互联网寒冬下成功拿到阿里巴巴.今日头条.上海轻轻等公司offer,岗位是Java后端开发,因为发展原因最终选择去了上海轻轻,入职一年时间了,也成为了面 ...
- 【开发笔记】- Idea启动Gradle报错:Warning:Unable to make the module: reading, related gradle configuration was not found. Please, re-import the Gradle project and try again
报错信息: Warning:Unable to make the module: reading, related gradle configuration was not found. Please ...
- 在组件上使用v-model
(1) 等价于: 其中$event.target.value表示获取输入框的值. (2)当用在组件上时,v-model 则会这样: 其中$event表示$emit抛出的值,即$emit的第二个参数. ...