Codeforces Gym100425 D. Toll Road

D. Toll Road
time limit per test
1 second
memory limit per test
128 megabytes
input
standard input
output
standard output

Exactly N years ago, a new highway between two major cities was built. The highway runs from west to east. It was planned as one big segment of a toll road. However, new highway was not popular: drivers still used free roads.

After analyzing the situation, the administration decided to perform a marketing trick to increase the popularity of the new highway.

The highway was divided into segments. Initially, there was only one segment. Every odd year, each of the existing segments was divided into two new segments with lengths divided as X: Y. This means that the length of the western segment relates to the length of the eastern segment as X relates to Y. Every even year, each of the existing segments was also divided into two new segments, but this time, the ratio was Y: X. After each division, the first of the two resulting segments was declared a free road and the second one a toll road. Each year, the segments are numbered from 1 from west to east. For simplicity, X and Y are positive integers which sum up to exactly 100.

As a result, the administration was able to significantly increase the income: the drivers started to drive on free segments and did not dare to turn away at the sight of the next toll segment. But after N years, the plan of the highway became so complex that it is now hard to calculate the exact lengths of the segments.

Knowing the total length of the highway P, one can calculate the length Lk of the segment with number k using the formula

Lk = P × (X / 100)Ak × (Y / 100)Bk
for some integers Ak and Bk. Here, Ak is the number of years in which, during the division, this segment was in the part proportional to X, and Bk is the number of years when it was in the part proportional to Y.

You need to answer to the queries containing numbers Ki of segments. To answer each query, you must print the values of Aki and Bki for the corresponding segment.

Input

The first line of the input contains three integers: the number of years N (1 ≤ N ≤ 1018) that have elapsed since the highway was built, followed by the percentages X and Y (1 ≤ X, Y ≤ 99, X + Y = 100) used each year to divide the segments.

The second line contains one integer: the number of queries Q (1 ≤ Q ≤ 104).

The following Q lines contain queries. Each query is an integer Ki (1 ≤ Ki ≤ 1018), the number of some segment. It is guaranteed that the segment with such number exists.

Output

For each query, print two integers Aki and Bki on a separate line.

Sample test(s)
Input
3 25 75 4
1
3
5
8
Output
2 1
3 0
1 2
1 2

题意

一条公路,从第一年开始,每到奇数年把公路的每一段按照比例 A:B 分成两段,每到偶数年按照比例 B:A 分成两段,过了 N 年,第k段的长度为 Lk=P×(X100)Ak×(Y100)Bk ,输入 k ,询问Ak,Bk

题解

数据看起来很吓人。。实际上还是二分(又是二分。。),分割的过程可以表示成一个完全二叉树,边权是分割的比例, N 年后公路一共有2N段,然后 260=1152921504606846976 。。超过了询问的最大范围。。。当 N>60 ,考虑最左边的路径,发现权值是 A,B 交替出现的,于是初始化 A=(N60)/2,B=(N60)/2 ,如果 (N60) 是奇数, A+1 ,令 N=60 。然后又可以二分啦!在二分的过程中更新 ansa ansb 的值就好。

代码

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#define fout freopen("out.txt","w",stdout)
#define fin freopen("in.txt","r",stdin)

using namespace std;

long long N;
int X,Y,Q;
long long K,ans[2],A=0,B=0;
int mark=0;
void Find(long long x,int flag)
{
    long long m,l=1,r=N;
    m=(l+r)/2;
    while(1)
    {
        if(x<=m)
        {
            r=m;
            ans[flag]++;
            flag=!flag;
        }
        else
        {
            l=m+1;
            flag=!flag;
            ans[flag]++;
        }
        if(l==m||l==r)
            break;
        m=(l+r)/2;
    }
}
int main()
{
    scanf("%I64d%d%d%d",&N,&X,&Y,&Q);
    if(N>60)
    {
        A=B=(N-60)/2;
        if((N-60)&1)
        {
            A++;
            mark=1;
        }
        N=60;
    }
    N=1LL<<N;
    for(int i=0;i<Q;i++)
    {
        scanf("%I64d",&K);
        ans[0]=ans[1]=0;
        Find(K,mark);
        printf("%I64d %I64d\n",ans[0]+A,ans[1]+B);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值