「Codeforces」758D(贪心细节/dp)

题意:原题在这

Alexander is learning how to convert numbers from the decimal system to any other, however, he doesn‘t know English letters, so he writes any number only as a decimal number, it means that instead of the letter A he will write the number 10. Thus, by converting the number 475from decimal to hexadecimal system, he gets 11311 (475 = 1·162 + 13·161 + 11·160). Alexander lived calmly until he tried to convert the number back to the decimal number system.

Alexander remembers that he worked with little numbers so he asks to find the minimum decimal number so that by converting it to the system with the base n he will get the number k.

给定一个进制数及该进制下的串,求十进制下的该数

思路:

数串从后向前扫,如果某位及之前的十进制和小于给定进制则可以选,直至超过给定进制(贪心)

注意特判0的情况

代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define maxn 100000005
#define ll unsigned long long
using namespace std;
const ll inf=0x7FFFFFFFFFFFFFFFLL;

char c[65];
ll dp[65];
string s;
int n;

int main()
{
    cin>>n>>s;
    int len=s.size();
    ll ans=0,cnt=1;
    for(int i=len-1;i>=0;)
    {
        ll flag=1,digit=0,now=0,pw=1;
        for(int j=i;j>=0;)
        {
            ll k=(s[j]-‘0‘);//s[i]-‘0‘表示将串的i位转为数字
            if(now+k*pw<n&&now+k*pw>=0)//如果某位及之前的十进制和小于给定进制
            {
                now+=k*pw,pw*=10;//可以选
                j--,digit++;//选完之后继续向前扫
                if(j<0)//j<0时退出
                {
                    ans+=cnt*now;
                    cout<<ans<<endl;
                    return 0;
                }
            }
            else if(now+k*pw>=n||now+k*pw<0)//如果不能选(特判)
            {
                while(s[j+1]==‘0‘&&digit!=1)//如果下一位是0且当前位下选过
                {
                    j++;
                    digit--;
                }
                pw/=10;
                i=j,flag=0;
                break;
            }
        }
        ans+=now*cnt;
        cnt*=n;
    }
    cout<<ans<<endl;
    return 0;
}

附上dp方法核心代码:

for (int i=1;i<=len;i++) c[i]=s[i-1];
for (int i=0;i<=len;i++) dp[i]=inf;
dp[0]=0;
for (int i=1;i<=len;i++)
{
    for (int j=i;j<=len;j++)
    {
        now=now*10+c[j]-‘0‘;
        if (now>=n) break;//贪心求比n小的最大值
        if (c[i]==‘0‘&& j>i) break;//判断中间的零
        dp[j]=min(dp[j],dp[i-1]*n+now);
        for (int m=1;m<=len;m++)
        {
            cout<<dp[m]<<‘ ‘;
        }
    }
    cout<<endl;
}
cout<<dp[len]<<endl;

原文地址:https://www.cnblogs.com/LocaEtric/p/9614980.html

时间: 2024-08-27 13:52:36

「Codeforces」758D(贪心细节/dp)的相关文章

「Codeforces」245H Queries for Number of Palindromes (区间dp)

题意:原题在这 You've got a string s = s1s2... s|s| of length |s|, consisting of lowercase English letters. There also are q queries, each query is described by two integers li, ri (1 ≤ li ≤ ri ≤ |s|). The answer to the query is the number of substrings of

LG2145 「JSOI2007」祖码 区间DP

问题描述 LG2145 题解 把颜色相同的一段看做一个点. 然后类似于合唱队区间DP即可. 但是这题好像出过一些情况,导致我包括题解区所有人需要特判最后一个点. \(\mathrm{Code}\) #include<bits/stdc++.h> using namespace std; template <typename Tp> void read(Tp &x){ x=0;char ch=1;int fh; while(ch!='-'&&(ch<'0

LG4158 「SCOI2009」粉刷匠 线性DP

问题描述 LG4158 题解 设\(opt[i][j][k]\)代表到\((i,k)\)刷了\(j\)次的方案数. 一开始DP顺序有点问题,调了很长时间. 务必考虑清楚DP顺序问题 \(\mathrm{Code}\) #include<bits/stdc++.h> using namespace std; template <typename Tp> void read(Tp &x){ x=0;char ch=1;int fh; while(ch!='-'&&

Codeforces 459E Pashmak and Graph(dp+贪心)

题目链接:Codeforces 459E Pashmak and Graph 题目大意:给定一张有向图,每条边有它的权值,要求选定一条路线,保证所经过的边权值严格递增,输出最长路径. 解题思路:将边按照权值排序,每次将相同权值的边同时加入,维护每个点作为终止点的最大长度即可. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 3

loj #6091. 「Codeforces Round #418」幻想特快

#6091. 「Codeforces Round #418」幻想特快 1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 #include<queue> 6 using namespace std; 7 #define maxn 10000 8 int n,a[maxn],b[maxn],p[maxn],nxt1,nxt2,tot,

Codeforces 830A. Office Keys (背包dp+贪心) / (二分+贪心)

题目链接: http://codeforces.com/problemset/problem/830/A 题意: n个人,k个钥匙(n<=k),p表示这些人要到达的位置 给出n个人的位置以及钥匙的位置,问花时间最多的那个人用时最少是多少?? 思路: 二分+贪心: 二分最少时间,需要对a,b位置数组排序,我们check函数只需要从左到右一个一个找过去,因为如果选后边的点,可能会使结果更差,假如当前这个人选后面的点,那可能会选中后面的人可以选的唯一的钥匙,不会使解更优. check(40)的时候答案

「JSOI2013」贪心的导游

「JSOI2013」贪心的导游 传送门 多次询问区间内%一个数的最大值 我们不妨设这个数为M_sea 值域比较小所以考虑分块维护. 我们观察到对于给定的一个 \(p\) ,函数 \(y = x \% p\) 是分段的且在各段内递增,所以我们可以先分块,记一下每个块内小于等于某个数的最大值,记为 \(g_i\) ,那么我们显然是要在所有的 \(i = kp - 1, k \ge 1\) 中查询 \(g_i\) 并减掉会被 % 掉的部分,那么我们就可以预处理出一个块内的答案了,然后查询的时候暴力查就

「BZOJ4029」[HEOI2015] 定价 贪心

「BZOJ4029」[HEOI2015] 定价 2015年4月28日2,7490 Description 在市场上有很多商品的定价类似于 999 元.4999 元.8999 元这样.它们和 1000 元.5000 元和 9000 元并没有什么本质区别,但是在心理学上会让人感觉便宜很多,因此也是商家常用的价格策略.不过在你看来,这种价格十分荒谬.于是你如此计算一个价格 p(p 为正整数)的荒谬程度: 1.首先将 p 看做一个由数字组成的字符串(不带前导 0): 2.然后,如果 p 的最后一个字符是

「SCOI2014」方伯伯的商场之旅

「SCOI2014」方伯伯的商场之旅 题目描述 方伯伯有一天去参加一个商场举办的游戏.商场派了一些工作人员排成一行.每个人面前有几堆石子.说来也巧,位置在 \(i\) 的人面前的第 \(j\) 堆的石子的数量,刚好是 \(i\) 写成 \(K\) 进制后的第 \(j\) 位. 现在方伯伯要玩一个游戏,商场会给方伯伯两个整数 \(L,R\).方伯伯要把位置在 \([L, R]\) 中的每个人的石子都合并成一堆石子.每次操作,他可以选择一个人面前的两堆石子,将其中的一堆中的某些石子移动到另一堆,代价