原文链接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 动态规划的更多相关文章

  1. CodeForces 515C. Drazil and Factorial

    C. Drazil and Factorial time limit per test 2 seconds memory limit per test 256 megabytes input stan ...

  2. codeforces 515C. Drazil and Factorial 解题报告

    题目链接:http://codeforces.com/problemset/problem/515/C 题目意思:给出含有 n 个只有阿拉伯数字的字符串a(可能会有前导0),设定函数F(a) = 每个 ...

  3. CodeForces 515C Drazil and Factorial (水题)

    题意:给出含有 n 个只有阿拉伯数字的字符串a,设定函数F(a) = 每个数字的阶乘乘积 .需要找出 x,使得F(x) = F(a),且组成 x 的数字中没有0和1.求最大的 x 为多少. 析:最大, ...

  4. [codeforces 516]A. Drazil and Factorial

    [codeforces 516]A. Drazil and Factorial 试题描述 Drazil is playing a math game with Varda. Let's define  ...

  5. Codeforces Round #292 (Div. 1)A. Drazil and Factorial 构造

    A. Drazil and Factorial 题目连接: http://codeforces.com/contest/516/problem/A Description Drazil is play ...

  6. codeforces 515C C. Drazil and Factorial(水题,贪心)

    题目链接: C. Drazil and Factorial time limit per test 2 seconds memory limit per test 256 megabytes inpu ...

  7. 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 ...

  8. CF Drazil and Factorial (打表)

    Drazil and Factorial time limit per test 2 seconds memory limit per test 256 megabytes input standar ...

  9. Codeforces Round #292 (Div. 2) C. Drazil and Factorial

    题目链接:http://codeforces.com/contest/515/problem/C 给出一个公式例如:F(135) = 1! * 3! * 5!; 现在给你一个有n位的数字a,让你求这样 ...

随机推荐

  1. Ex 2_16 给定一个无穷数组..._第二次作业

    先比较数组的A[0]元素,若不相等接下来比较A[1],A[2],A[4],A[8]…,若找到一个区间A[2n-1]<x<A[2n],再对这个区间进行折半查找操作.总的时间为O(logn). ...

  2. 【原创】大数据基础之Hive(3)最简绿色部署

    hadoop部署参考:https://www.cnblogs.com/barneywill/p/10428098.html 1 拷贝到所有服务器上并解压 # ansible all-servers - ...

  3. [Linux]关于字节序的解析

    剥鸡蛋的故事 <格列佛游记>中记载了两个征战的强国,你不会想到的是,他们打仗竟然和剥鸡蛋的姿势有关. 很多人认为,剥鸡蛋时应该打破鸡蛋较大的一端,这群人被称作“大端(Big endian) ...

  4. MicroPython的开发板

    比如: pyboard micro:bit ESP8266/ESP32 stm32等等 什么是pyboard? pyboard是官方的MicroPython微控制器板,完全支持软件功能.硬件有: ST ...

  5. Python中join()函数方法

    函数:string.join() Python中有join()和os.path.join()两个函数,具体作用如下:    join():    连接字符串数组.将字符串.元组.列表中的元素以指定的字 ...

  6. VBS计时器

    用VBS实现一个以分钟为单位的计时器: rem msgbox now 'now is the system para msgbox "Timer",,"CreatedBy ...

  7. 【翻译】关于vertical-align所有你需要知道的

    本文是翻译过来的,如果有不对的地方还请指教~,原文链接:Vertical-Align: All You Need To Know 前面一些说明,可以略过不看吧 我经常需要对元素进行垂直方向上的布局. ...

  8. Java的动手动脑(五)

    日期:2018.11.1 星期四 博客期:021 Part1: 运行代码 class Grandparent { public Grandparent() { System.out.println(& ...

  9. selenium 获取input输入框中的值的方法

    方法一:获取input的文本值 <input class="form-text-normal" id="txtName" name="Name& ...

  10. easyUI详解

    1.EasyUI 是前端框架,封装大量 css和封装大量 JS 2.使用前端框架时,给标签定义class 属性,就会有样式和脚本功能了 3.data-options 属性是定义 easyui 属性的, ...