原文链接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. linux强制将数据写入磁盘,防止丢失内存的数据

    sync命令文件系统管理 sync命令用于强制被改变的内容立刻写入磁盘,更新超块信息. 在Linux/Unix系统中,在文件或数据处理过程中一般先放到内存缓冲区中,等到适当的时候再写入磁盘, 以提高系 ...

  2. Fiddler 抓包工具

    序章 Fiddler是一个蛮好用的抓包工具,可以将网络传输发送与接受的数据包进行截获.重发.编辑.转存等操作.也可以用来检测网络安全.反正好处多多,举之不尽呀!当年学习的时候也蛮费劲,一些蛮实用隐藏的 ...

  3. 深入Golang调度器之GMP模型

    前言 随着服务器硬件迭代升级,配置也越来越高.为充分利用服务器资源,并发编程也变的越来越重要.在开始之前,需要了解一下并发(concurrency)和并行(parallesim)的区别. 并发:  逻 ...

  4. Android广播机制

    原文出处: Android总结篇系列:Android广播机制 1.Android广播机制概述 Android广播分为两个方面:广播发送者和广播接收者,通常情况下,BroadcastReceiver指的 ...

  5. swift 学习- 17 -- 析构器

    // 析构器 只适用与 类类型, 当一个类的实例被释放之前, 析构器会被立即调用, 析构器用关键字 deinit 来标示, 类似于构造器要用 init 来标示 // 析构过程原理 // Swift 会 ...

  6. ORACLE的数据类型的长度合集

    --  ORACLE的数据类型常用的数据库字段类型如下:字段类型 中文说明 限制条件 其它说明CHAR 固定长度字符串 最大长度2000 bytesVARCHAR2 可变长度的字符串 最大长度4000 ...

  7. ORACLE_修改实例的内存大小

    注:本文来源于:星火spark  <Oracle的实例占用内存调整> ORACLE_修改实例的内存大小 一:修改oracle数据库实例内存大小脚本 ---- 1.操作 (oracle使用内 ...

  8. Jquery如何获取iframe里面body的html呢?

    如果是自己网页的话,可以这样,$("iframe").contents().find("body").html();意思是,获取iframe里面页面body的内 ...

  9. java多线程快速入门(二十)

    1.Java.util的线程安全工具类 Vector(线程安全) ArrayList(线程不安全) HashTable(线程安全) HashMap(线程不安全) 2.将线程不安全集合变为线程安全集合 ...

  10. 对于stark(curd)插件的使用简单介绍

    一.创建表 from django.db import models from django.db import models class Department(models.Model): &quo ...