CodeForces 516A Drazil and Factorial 动态规划
原文链接http://www.cnblogs.com/zhouzhendong/p/8990592.html
题目传送门 - CodeForces 516A
题意
对于一个正整数$x$,$f(x)=x$各个数位的阶乘之积。
给定一个数$a$,满足$f(a)>1$,求一个最大的不含有$0$或者$1$的$x$满足$f(x)=f(a)$。
$a<10^{16}$
题解
我们将$f(a)$分解质因数并统计各个质因数个数作为状态。
首先考虑到每一个数位都是$2$~$9$的,质因数只可能有$4$种。
而且,即便是贡献最大的$9$,也只会贡献$7$个质因数$2$、$4$个质因数$3$、$1$个质因数$5$和$1$个质因数$7$。
考虑到$a$最多只有$15$位,所以质因数$2,3,5,7$的总个数最多分别为$105,60,15,15$。
我们用$dp[s2][s3][s5][s7]$来表示$f(x)=2^{s2}3^{s3}5^{s5}7^{s7}$的最大$x$。
显然这个$x$会很大,为了避免写高精度,我们可以这样考虑:
由于我们只需要知道$x$分别由几个$2$、几个$3$、…、几个$9$组成,就可以唯一确定一个最大的$x$。(按照顺序从大到小)
所以,我们考虑换一种储存方式。考虑到$2$最多只有$105$个,所以我们可以给每一个数字$7$个二进制位(事实上我代码里只有$6$位压缩也过了),每$7$个二进制位里面保存着他所代表的数的个数信息。由于只需要保存$8$个数字的信息,所以总共需要$56$个二进制位,开$64$位整型即可。至于比较大小,太简单不多说。
然后,对于当前状态,从$2$到$9$枚举之前放了哪一个数字,然后根据之前的转移即可。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=20,S2=105,S3=60,S5=15,S7=15;
int n,tot[4];
LL dp[S2+1][S3+1][S5+1][S7+1];
int lists[N][4]={
{0,0,0,0},
{0,0,0,0},
{1,0,0,0},
{0,1,0,0},
{2,0,0,0},
{0,0,1,0},
{1,1,0,0},
{0,0,0,1},
{3,0,0,0},
{0,2,0,0}
};
char s[N];
int cntd(LL x){
int tot=0;
for (int i=9;i>=2;i--)
tot+=x&63LL,x>>=6;
return tot;
}
bool bigger(LL a,LL b){
int c1=cntd(a),c2=cntd(b);
if (c1!=c2)
return c1>c2;
for (int i=9;i>=2;a>>=6,b>>=6,i--)
if ((a&63LL)!=(b&63LL))
return (a&63LL)>(b&63LL);
return 0;
}
int main(){
scanf("%d%s",&n,s);
for (int i=2;i<=9;i++)
for (int j=0;j<4;j++)
lists[i][j]+=lists[i-1][j];
memset(tot,0,sizeof tot);
for (int i=0;i<n;i++)
for (int j=0;j<4;j++)
tot[j]+=lists[s[i]-'0'][j];
memset(dp,-1LL,sizeof dp);
dp[0][0][0][0]=0;
for (int s2=0;s2<=tot[0];s2++)
for (int s3=0;s3<=tot[1];s3++)
for (int s5=0;s5<=tot[2];s5++)
for (int s7=0;s7<=tot[3];s7++)
for (int i=2;i<=9;i++){
int t2=s2-lists[i][0];
int t3=s3-lists[i][1];
int t5=s5-lists[i][2];
int t7=s7-lists[i][3];
if (t2<0||t3<0||t5<0||t7<0)
continue;
if (dp[t2][t3][t5][t7]==-1)
continue;
LL now=dp[t2][t3][t5][t7]+(1LL<<((9-i)*6));
if (dp[s2][s3][s5][s7]==-1||bigger(now,dp[s2][s3][s5][s7]))
dp[s2][s3][s5][s7]=now;
}
LL x=dp[tot[0]][tot[1]][tot[2]][tot[3]];
for (int i=9;i>=2;i--,x>>=6)
for (int j=0;j<(x&63LL);j++)
putchar('0'+i);
return 0;
}
CodeForces 516A Drazil and Factorial 动态规划的更多相关文章
- CodeForces 515C. Drazil and Factorial
C. Drazil and Factorial time limit per test 2 seconds memory limit per test 256 megabytes input stan ...
- codeforces 515C. Drazil and Factorial 解题报告
题目链接:http://codeforces.com/problemset/problem/515/C 题目意思:给出含有 n 个只有阿拉伯数字的字符串a(可能会有前导0),设定函数F(a) = 每个 ...
- CodeForces 515C Drazil and Factorial (水题)
题意:给出含有 n 个只有阿拉伯数字的字符串a,设定函数F(a) = 每个数字的阶乘乘积 .需要找出 x,使得F(x) = F(a),且组成 x 的数字中没有0和1.求最大的 x 为多少. 析:最大, ...
- [codeforces 516]A. Drazil and Factorial
[codeforces 516]A. Drazil and Factorial 试题描述 Drazil is playing a math game with Varda. Let's define ...
- Codeforces Round #292 (Div. 1)A. Drazil and Factorial 构造
A. Drazil and Factorial 题目连接: http://codeforces.com/contest/516/problem/A Description Drazil is play ...
- codeforces 515C C. Drazil and Factorial(水题,贪心)
题目链接: C. Drazil and Factorial time limit per test 2 seconds memory limit per test 256 megabytes inpu ...
- Codeforces Round #292 (Div. 2) C. Drazil and Factorial 515C
C. Drazil and Factorial time limit per test 2 seconds memory limit per test 256 megabytes input stan ...
- CF Drazil and Factorial (打表)
Drazil and Factorial time limit per test 2 seconds memory limit per test 256 megabytes input standar ...
- Codeforces Round #292 (Div. 2) C. Drazil and Factorial
题目链接:http://codeforces.com/contest/515/problem/C 给出一个公式例如:F(135) = 1! * 3! * 5!; 现在给你一个有n位的数字a,让你求这样 ...
随机推荐
- linux ln 命令使用参数详解(ln -s 软链接)
ln是linux中一个非常重要的命令,它的功能是为某一个文件在另外一个位置建立一个同步的链接.当我们需要在不同的目录,用到相同的文件时,我们不需要在每一个需要的目录下都放一个必须相同的文件,我们只要在 ...
- ActiveMQ在Windows下的安装与启动(懒人专属)
其实这些ActiveMQ官网都有,但是如果你懒得看官网,那就直接看这吧! 1. 官网下载最新的ActiveMQ安装包 apache-activemq-x.x.x-bin.zip并解压 2.进入安装 ...
- postgresql 触发器 更新操作
1 前言 功能需求:当一张表格某个字段变化,另一张表某个字段写入该值 2 代码 CREATE OR REPLACE FUNCTION "public"."synStatu ...
- python基础--压缩文件
1)怎么压缩备份多个文件 使用zipfile 创建压缩文件 查看信息 解压缩 # 创建 import zipfile # os.chdir('test') my_zip = zipfile.ZipFi ...
- NPOI写Excel,Microsoft.Office.Interop.excel.dll 转换Excel为PDF
首先要引用NPOI动态库和Microsoft.Office.Interop.excel.dll (Microsoft.Office.Interop.excel.dll 下载链接 ,下载以后解压文件,把 ...
- Oracle 行转列pivot 、列转行unpivot 的Sql语句总结
这个比较简单,用||或concat函数可以实现 select concat(id,username) str from app_user select id||username str from ap ...
- linux符号与正则表达式
特殊符号 > 或者1> 标准输出重定向 先把文件的内容清空 再放入新的内容 >> 或 2>> 追加重定向 把内容放入文件的最后一行 1 ...
- BeautifulSoup的基本操作
>>> from bs4 import BeautifulSoup #导入 >>> soup = BeautifulSoup(url.content," ...
- cf1144G 将串分解成单调递增和递减子串(贪心)
这算哪门子dp.. 具体做法就是贪心,建立两个vector存递增序列递减序列,操作过程中a可以合法地匀一个给b 就是判断第i个数放在递增序列里还是放在递减序列里,需要根据后面的数来进行决策 #incl ...
- CF1029E
一个看起来就不对的贪心居然是正解... 但仔细思考一下,这种贪心倒的确找不到反例.. 贪心思想:每次找出离根节点最远的点,然后由根节点向这个点的父节点连边,一直连到所有点都能被覆盖即可,这样构造出的一 ...