天天看點

Codeforces Round #268 (Div. 1) C. Hack it!(二分+尺取/構造,好題)

C. Hack it! time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output

Little X has met the following problem recently. 

Let's define f(x) as the sum of digits in decimal representation of number x (for example, f(1234) = 1 + 2 + 3 + 4). You are to calculate 

Codeforces Round #268 (Div. 1) C. Hack it!(二分+尺取/構造,好題)

Of course Little X has solved this problem quickly, has locked it, and then has tried to hack others. He has seen the following C++ code: 

ans = solve(l, r) % a;
    if (ans <= 0)
      ans += a;

      

This code will fail only on the test with 

Codeforces Round #268 (Div. 1) C. Hack it!(二分+尺取/構造,好題)

. You are given number  a, help Little X to find a proper test for hack. Input

The first line contains a single integer a (1 ≤ a ≤ 1018).

Output

Print two integers: l, r (1 ≤ l ≤ r < 10200) — the required test data. Leading zeros aren't allowed. It's guaranteed that the solution exists.

Examples input

46
      

output

1 10
      

input

126444381000032
      

output

2333333 2333333333333      

題意:

定義f(x)為x在十進制下的各位數字之和。

給定a,需要你給出一個l,r(1 <= l <= r <= 1e200)使得(f(l) + ... +f(r))能被a整除。

題目確定有解。

(1 <= a <= 1e18)

題解:

姿勢1:[一套尺取+二分連招]

令s(x) = f(1)+f(2)+…+f(x)。

我們隻需找到s(R)%a = s(L-1)%a就美滋滋了

我們使用二分查詢找到最小的且滿足g(R)>=a

的值R, 接下來令L=1,然後跑一個雙指針,調整

L,R的值即可。至于s(x)怎麼求,我們把每一個

數位對答案的貢獻加起來即可。

姿勢2:[構造]

注意到f(x+1e18)=f(x)+1。

故s(x+1e18)=s(1e18)+s(x)+x。

即s(x+1e18)-s(x) = s(1e18)+x

讓 s(1e18)+x%a==0,x= a-s(1e18)%a

L = a-s(1e18)%a+1,R = L + 1e18- 1

于是一組合法解就神不知鬼不知覺地構造出來了

代碼請有興趣的讀者自行完成~

方法1:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#include<stack>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
ll get(ll x)
{
    ll ans=0;
    for(ll i=1;i<=x;i*=1ll*10)
    {
        int d=(x/i)%10;
        ll q=x/(1ll*10*i);
        ans+=i*q*45;
        rep(j,1,d) ans+=j*i;
        ll t=x-(x/i)*i;
        ans+=(t+1)*d;
    }
    return ans;
}

ll get1(ll x)
{
    ll ans=0;
    while(x)
    {
        ans+=x%10;
        x/=10;
    }
    return ans;
}

int main()
{
    ll a;
    scanf("%lld",&a);
    ll l=0,r=1e17,ans=-1;
    while(l<=r)
    {
        ll m=(l+r)/2;
        if(get(m)>=a)
            ans=m,r=m-1;
        else l=m+1;
    }
    l=1,r=ans;
    ll now=get(ans);
    while(now!=a)
    {
        if(now>a) now-=get1(l++);
        else if(now<a) now+=get1(++r);
    }
    printf("%lld %lld\n",l,r);
    return 0;
}
           

方法2:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#include<stack>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
ll get(ll x)
{
    ll ans=0;
    for(ll i=1;i<=x;i*=1ll*10)
    {
        int d=(x/i)%10;
        ll q=x/(1ll*10*i);
        ans+=i*q*45;
        rep(j,1,d) ans+=j*i;
        ll t=x-(x/i)*i;
        ans+=(t+1)*d;
    }
    return ans;
}


int main()
{
    ll a;
    scanf("%lld",&a);
    ll t=get(1e17)%a;
    ll l=a-t+1,r=l+1e17-1;
    printf("%lld %lld\n",l,r);
    return 0;
}
           

繼續閱讀