zoukankan      html  css  js  c++  java
  • 【AGC011E】Increasing Numbers

    题目

    题目链接:https://atcoder.jp/contests/agc011/tasks/agc011_e
    我们说一个数是“递增的”,当且仅当对于它的任意相邻的两位都有左边小于等于右边。
    (1558), (11), (3) 是递增的,(20170312)(19260817) 就不是。
    现在给你一个数 (n),问最少可以被表示成几个递增的数之和。
    比如 (80 = 56 + 24)(2017 = 1349 + 668), (2019 = 1669 + 237 + 113)
    (1 ≤ n ≤ 10^{500000})

    思路

    任何一个递增的数,都可以表示成 (9)(111cdots 1) 的和。注意这里可以是 (0)(1)
    所以如果答案为 (k),那么有

    [n=sum^{9k}_{i=1}frac{10^{a_i}-1}{9} ]

    也就是

    [9n+9k=sum^{9k}_{i=1}10^{a_i} ]

    因为可以有 (0)(1),所以其实就是要求出最小的 (k),使得 (9n+9k) 十进制下每一位之和不超过 (9k)
    二分,然后每次 (O(n)) 判断即可。时间复杂度 (O(nlog n))

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N=500010;
    int len,a[N+10],b[N+10];
    char s[N+10];
    
    void mul(int *a,int b)
    {
    	int t=0;
    	for (int i=N;i>=1;i--)
    	{
    		a[i]=a[i]*b+t;
    		t=a[i]/10;
    		a[i]%=10;
    	}
    }
    
    void inc(int *a,int b)
    {
    	int t=0;
    	for (int i=N;i>=1;i--)
    	{
    		a[i]=a[i]+(b%10)+t;
    		t=a[i]/10;
    		a[i]%=10;
    		b/=10;
    	}
    }
    
    bool check(int k)
    {
    	memcpy(b,a,sizeof(a));
    	inc(b,9*k);
    	int sum=0;
    	for (int i=1;i<=N;i++) sum+=b[i];
    	return sum<=9*k;
    }
    
    int main()
    {
    	scanf("%s",s+1);
    	len=strlen(s+1);
    	for (int i=1;i<=len;i++)
    		a[N-len+i]=s[i]-48;
    	mul(a,9);
    	int l=1,r=len,mid;
    	while (l<=r)
    	{
    		mid=(l+r)>>1;
    		if (check(mid)) r=mid-1;
    			else l=mid+1;
    	}
    	cout<<r+1;
    	return 0;
    }
    
  • 相关阅读:
    python web 2
    python web1(解析url)
    webstrom 今天突然要激活
    数组排序 记录一下
    浏览器添加随机数去除缓存
    vue-cli 安装报错
    vue 初始化项目报错
    深拷贝和浅拷贝
    css3 属性 clip-path
    js数组去重
  • 原文地址:https://www.cnblogs.com/stoorz/p/15419927.html
Copyright © 2011-2022 走看看