AGC 011 E Increasing Numbers - 贪心

题目大意:问至少多少各位数不减的数字,其和为N。len(N)<=5e5。
题解:各位数字不减的数字可以表示为9个每位都是1的数字之和(位数可以等于0)。一个a位都是1都数字是 1 0 a − 1 9 \frac{10^a-1}9 910a1。假设用了k个数字,那么相当于是找一些a[i]使得 ∑ i = 1 9 k 1 0 a i = 9 n + 9 k \sum_{i=1}^{9k}10^{a_i}=9n+9k i=19k10ai=9n+9k成立。这个可以证明等价于 9 n + 9 k 9n+9k 9n+9k的各位数字之和不超过 9 k 9k 9k。可以显然发现答案最坏也就是 O ( l e n ( n ) ) O(len(n)) O(len(n))级别的,而暴力进位的复杂度可以被证明是均摊 O ( l e n ( n ) ) O(len(n)) O(len(n))的。这样就做完了。

#include
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;const int N=500010;char str[N];
struct bignum{
	int a[N*10],n,s;bignum() { memset(a,0,sizeof a),n=s=0; }
	inline int input() { scanf("%s",str+1),n=(int)strlen(str+1);rep(i,1,n) a[n-i+1]=str[i]-'0';return 0; }
	inline bignum& operator+=(int t)
	{	s-=a[1],a[1]+=t;int i=1,jw=a[1]/10;for(;jw;s-=a[i+1],a[i+1]+=jw,a[i]%=10,jw=a[++i]/10);rep(j,1,i) s+=a[j];n=max(n,i);return *this;	}
	inline bignum& operator*=(int t)
	{	rep(i,1,n) a[i]*=t;for(int i=1,jw=a[1]/10;i<=n||jw;a[i+1]+=jw,a[i]%=10,jw=a[++i]/10);while(a[n+1]) n++;s=0;for(int i=1;i<=n;i++) s+=a[i];return *this;	}
}x;
int main() { x.input(),(x*=9)+=9;for(int k=1;;x+=9,k++) if(x.s<=9*k) return !printf("%d\n",k);return 0; }

你可能感兴趣的:(AGC 011 E Increasing Numbers - 贪心)