HDU 5710 digit sum

题意:

定义S(N) 为数字N每个位上数字的和。

在给两个数a,b,求最小的正整数n,使得 a×S(n)=b×S(2n)。

分析:

为我们要找到满足 a * S(n) = bS(2n) 的最小的n的值,首先第一个想法肯定暴力啊..但是暴力肯定不对啊... 比如--->2 3 输出5589

也就是说从整体(一个数字)到部分(各个位数)的思路是行不通的,因为是digit 所以可以尝试由部分到整体也就是构造呀。

那么如何构造呢?从若不存在S(2n) 那么我们的构造一定是从低位构造到高位。

但是有S(2n)那么是否可以根据S(N)和 S(2N)构造出一定规律呢。

题目中没有给任何信息那么,因为是发现构造规律那么是要研究2的位数。

容易发现 当位数属于[0,4]时候 2n后 各个位数的贡献值会翻倍,不同的是,[5,9]时各个位数的贡献值是2n-9

设cnt 是n中各个位数大于等于5的

S(2n)= 2*S(n)-9cnt

那么可以整理出来的是

9b:2b-a=S(n):cnt

那么我们可以得到S(n) 为 9b cnt为 2b-a

那么现在就变成了我们已经知道S(n)和cnt为多少来求最小的N

那么贪心的填一填啊

(先填后面填到9)

再填一下... 前面的...

有几个特判

1.2b-a=0时候 S为任意值 必须满足那么可以输出n=1;

2.a>2b不存在

3.a<2b 必须满足b<=5a

#include  <bits/stdc++.h>
using namespace std;
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        int a,b;
        cin >> a >> b;
        int cnt = 2*b-a;
        int s = b*9;
        if(a == 2*b)
        {
            cout << 1 <<endl;
            continue;
        }
        if(a>2*b||5*a<b)
        {
            cout<< 0 <<endl;
            continue;
        }
        int gcd = __gcd(cnt,s);
        cnt/=gcd;
        s/=gcd;
        string ans=string(cnt,‘5‘);
        //看别人代码学到的操作这个函数很好用呀
        //cout<<ans<<endl;
        s-=5*cnt;
        int val;
        for(int i=ans.size()-1;i>=0;i--)
        {
            val=min(s,4);
            ans[i]+=val;
            s-=val;
        }
        while(s)
        {
            val=min(s,4);
            ans=char(val+‘0‘)+ans;
            s-=val;
        }
        cout<<ans<<endl;
    }
    return 0;
}

原文地址:https://www.cnblogs.com/muvseea/p/8971767.html

时间: 2024-10-12 17:39:26

HDU 5710 digit sum的相关文章

hdu 4825 Xor Sum(trie+贪心)

hdu 4825 Xor Sum(trie+贪心) 刚刚补了前天的CF的D题再做这题感觉轻松了许多.简直一个模子啊...跑树上异或x最大值.贪心地让某位的值与x对应位的值不同即可. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <cmath> 6 #define CLR(a,b) memset((a)

HDU 1024 Max Sum Plus Plus --- dp+滚动数组

HDU 1024 题目大意:给定m和n以及n个数,求n个数的m个连续子系列的最大值,要求子序列不想交. 解题思路:<1>动态规划,定义状态dp[i][j]表示序列前j个数的i段子序列的值,其中第i个子序列包括a[j], 则max(dp[m][k]),m<=k<=n 即为所求的结果 <2>初始状态: dp[i][0] = 0, dp[0][j] = 0; <3>状态转移: 决策:a[j]自己成为一个子段,还是接在前面一个子段的后面 方程: a[j]直接接在前面

[2016-03-28][HDU][1024][Max Sum Plus Plus]

时间:2016-03-28 17:45:33 星期一 题目编号:[2016-03-28][HDU][1024][Max Sum Plus Plus] 题目大意:从n个数字提取出一定数字组成m个部分,使得这个部分的总和最大 分析: dp[i][j]表示前i段计算第j个数字,dp[i][j] = max(dp[i - 1][j - 1] + a[j],dp[i][k] + a[j]); #include <algorithm> #include <cstring> #include &

HDU 3415 Max Sum of Max-K-sub-sequence 单调队列题解

本题又是一题单调队列题解. 技巧就是需要计算好前n项和Sn = a1 + a2 + ... an 这样方便处理. 记录一条单调队列,其意义是: q(head), q(head+1), ...q(tail) 其中头q(head)代表当前最佳解的起点 这样我们只需要在求某点为结尾的S[i] - S[q(head)就得到当前最佳值. 了解了单调数列,知道其中的记录意义,那么这道题就没有难度了.我也是了解这些信息之后就自己敲出代码的. 不过有些细节没写好也让我WA了几次. 最近少刷水题,而一直都是每天一

hdu 2576 Another Sum Problem

题目大意:求前n项和的前n项和. 数学推导题,f(n)=n*(n+1)*(n+2)/6 推导思路如下: #include"cstdio" #include"cstring" #include"cmath" #include"cstdlib" #include"iostream" #include"algorithm" #include"queue" using nam

hdu 3415 Max Sum of Max-K-sub-sequence(单调队列)

题目链接:hdu 3415 Max Sum of Max-K-sub-sequence 题意: 给你一串形成环的数,让你找一段长度不大于k的子段使得和最大. 题解: 我们先把头和尾拼起来,令前i个数的和为sum[i]. 然后问题变成了求一个max{sum[i]-sum[j]}(i-k<j<i) 意思就是对于每一个sum[i],我们只需要找一个满足条件的最小的sum[j],然后我们就可以用一个单调队列来维护. 1 #include<bits/stdc++.h> 2 #define F

Hdu 1024 Max Sum Plus Plus (dp)

题目链接: Hdu 1024 Max Sum Plus Plus 题目描述: 给出n个数,问m段连续子序列的和相加最大是多少? 解题思路: dp[i][j]表示把前i个元素(包括第i个),分成j段的最大和.状态转移方程就是dp[i][j] = max (dp[i-1][j] + arr[j],  max( dp[k][j-1]) + arr[j]),其中0<k<i.(第i个元素是保存在第j段,还是自己单独成段) 由于1<=n<=1000,000.n*n的数组肯定会爆炸,所以要对方程

HDU - 4961 Boring Sum

Problem Description Number theory is interesting, while this problem is boring. Here is the problem. Given an integer sequence a1, a2, -, an, let S(i) = {j|1<=j<i, and aj is a multiple of ai}. If S(i) is not empty, let f(i) be the maximum integer in

hdu 4961 Boring Sum(高效)

题目链接:hdu 4961 Boring Sum 题目大意:给定ai数组; 构造bi, k=max(j|0<j<i,aj%ai=0), bi=ak; 构造ci, k=min(j|i<j≤n,aj%ai=0), ci=ak; 求∑i=1nbi?ci 解题思路:因为ai≤105,所以预先处理好每个数的因子,然后在处理bi,ci数组的时候,每次遍历一个数,就将其所有的因子更新,对于bi维护最大值,对于ci维护最小值. #include <cstdio> #include <c