codeforces1020E The very same Munchhausen

題面

題意

給出一個正整數a,問是否存在一個正整數n,滿足S(an)=S(n)/aS(a*n)=S(n)/an<=10500000n<=10^{500000}
S(x)S(x)表示x各個數位的數字和。

做法

首先可以考慮把n分成多個部分,使n形如b1+b_1+"0000"+b2++b_2+“0000”+b3......bk+b_3......b_k
這樣每一部分就相互獨立了,只要滿足i=1kaS(abi)S(bi)=0\sum_{i=1}^{k}a*S(a*b_i)-S(b_i)=0即可。
我們可以根據aS(abi)S(bi)=0a*S(a*b_i)-S(b_i)=0的正負將bib_i分成兩類,要求這兩類的和的絕對值相等。
因爲500000很大,所以其實在大多數的情況下,只要滿足等式,一般都不會超過範圍。
所以可以讓每類bib_i分別相等,這樣我們只要找到兩個數x,yx,y,使aS(ax)S(x)>0a*S(a*x)-S(x)>0aS(ay)S(y)<0a*S(a*y)-S(y)<0,然後x,yx,y再各自反覆多次即可。
不難發現x=1x=1肯定符合條件(a=1a=1時要特判)。
現在就要找到滿足aS(ay)S(y)<0a*S(a*y)-S(y)<0的y。
顯然要讓S(ay)S(a*y)儘可能小,那我們就可以考慮讓它大於等於10i10^i,且儘可能的接近10i10^i
可以考慮枚舉i,令y=10isy=\lceil \frac{10^i}{s} \rceil,然後看看是否滿足aS(ay)S(y)<0a*S(a*y)-S(y)<0,如果滿足計算此時的總長度是否小於等於500000,滿足則輸出,否則繼續,注意特判一下a是10i10^i的因數的情況。
這個構造n的方案顯然不是使n最小的,但是就此題n<=10500000n<=10^{500000}來說,已經足夠了。

代碼

#include<bits/stdc++.h>
#define ll long long
#define Z 5
#define MN 500000
#define N 500100
using namespace std;

ll a,g,A,B,sum;
string num,zero,ans;

inline ll gcd(ll u,ll v)
{
    for(;v;)
    {
	u%=v;
	swap(u,v);
    }
    return u;
}

inline ll S(ll u)
{
    ll res=0;
    for(;u;u/=10) res+=u%10;
    return res;
}

int main()
{
    ll i,j,tmp,t;
    for(i=1;i<=Z;i++) zero+='0';
    cin>>a;
    if(a==1)
    {
	puts("1");
	return 0;
    }
    B=S(a)*a-1;
    for(i=0,tmp=1;tmp;i++)
    {
	if(num[num.size()-1]!='9' && a*(S(a-tmp)+1)<sum+1)
	{
	    A=sum+1-a*(S(a-tmp)+1);
	    g=gcd(A,B);
	    if((A/g)*(Z+1)+(B/g)*(Z+num.size())<=MN)
	    {
		num[num.size()-1]++;
		break;
	    }
	}
	tmp=tmp*10;
	t=tmp/a;
	sum+=t;
	if(num.size() || t) num+=t+'0';
	tmp%=a;
    }
    if(!tmp)
    {
	if(a>sum)
	{
	    puts("-1");
	    return 0;
	}
	else if(a==sum)
	{
	    cout<<num;
	    return 0;
	}
	A=sum-a;
	g=gcd(A,B);
    }
    for(i=1;i<=(B/g);i++) ans+=num+zero;
    for(i=1;i<=(A/g);i++) ans+="1"+zero;
    cout<<ans;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章