BZOJ4725: [POI2017]Reprezentacje ró?nicowe

77 篇文章 0 订阅
32 篇文章 0 订阅

这题远没有它看起来那么可怕..
容易发现当n>70时a[n]就已远大于1e9,此时和a[n]有关的差只有a[n]-a[n-1]在n为偶数的情况下在1e9之内
于是打个70的表,如果当前的x在打表时没出现,就二分找已经出现的差有多少个

#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
#define inf 1e9
using namespace std;

const int maxn = 110000;

int n;
ll a[maxn];

struct node
{
    int p,q;
    ll x;
};
inline bool operator <(const node x,const node y){return x.x<y.x;}
set<node>S;
set<node>::iterator it,it1;

ll t[maxn]; int tp;

int main()
{
    a[1]=1; S.insert((node){1,1,0});
    a[2]=2; S.insert((node){2,1,1}); it1=S.find((node){2,1,1}); t[++tp]=1;

    ll now=1; int u=70;
    for(int i=3;i<=u;i++)
    {
        if(i&1)
        {
            a[i]=a[i-1]*2ll;
            for(int j=i-1;j>=1;j--)
            {
                node tmp=(node){i,j,a[i]-a[j]};
                it=S.find(tmp);
                if(it==S.end()) S.insert(tmp),t[++tp]=tmp.x;
            }
        }
        else
        {
            it=it1;
            while(it!=S.end())
                it=S.find((node){0,0,++now});

            a[i]=a[i-1]+now;
            for(int j=i-1;j>=1;j--)
            {
                node tmp=(node){i,j,a[i]-a[j]};
                it=S.find(tmp);
                if(it==S.end()) S.insert(tmp),t[++tp]=tmp.x;
            }
        }
    }
    /*for(int i=1;i<=u;i++) printf("%lld\n",a[i]);
    puts(""); puts("");puts("");puts("");puts("");
    for(int i=1;i<=tp;i++) printf("%lld\n",t[i]);*/
    sort(t+1,t+tp+1);

    scanf("%d",&n);
    while(n--)
    {
        ll k; scanf("%lld",&k);
        it=S.find((node){0,0,k});
        if(it==S.end())
        {
            int l=1,r=tp;
            while(l<=r)
            {
                int mid=l+r>>1;
                if(t[mid]<k) l=mid+1;
                else r=mid-1;
            }l--;
            ll p=u+(k-l)*2ll;
            printf("%lld %lld\n",p,p-1);
        }
        else
        {
            printf("%d %d\n",(*it).p,(*it).q);
        }
    }

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值