【201703 HNSDFZ集训 R1T1 】B君的教育

Description

B 君最近听说了一个很惊人的性质,设 p=1+i ,对于每个高斯整数
x+yi ,我们都可以找到一个非负整数集合S 满足

kSpk=x+yi()

而你需要做的,就是在输入x 和y 的情况下,输出集合S。
如果你看不懂上面的题目,我们形式化的给出如下定义。
就是对于一个复数(Complex Number),如果他的实部和虚部都是整数,我们称之为高斯整数。
S 集合中不能有同样的元素,每个元素必须是非负整数。

Input

一行两个整数x,y。

Output

每行一个整数,从小到大输出,表示集合S。

Sample Input

2 0

Sample Output

2
3

Hint

对于100% 的数据,满足 |x|,|y|<=1018
对于50% 的数据,满足y = 0。
对于50% 的数据,满足 |x|,|y|<=102
以上两部分50% 是相互独立的。

题解

通过将 pk 打表出来,可以发现一个奥妙重重的规律:

pn=2(pn1+pn2)

证明很简单:
2(pn1+pn2)====2[pn2×(p+1)]pn2×(2i)pn2×p2pn

然后在发现在不考虑一个 pk 最多只能用1次的情况下,可以用 p0 p1 x+yi 表示出来。然后根据上面推出来的这个式子,k从0开始,若 pk 用了奇数次,就把它调整成1次,偶数次就调整成0次,如此向后,最终一定能得到解集。

#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
#define ll long long
using namespace std;

inline ll read(){
    ll x = 0, f = 1; char c = getchar();
    while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); }
    while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
    return x * f;
}

struct Complex{
    ll x, y;
    Complex(){}
    Complex (ll a, ll b){x = a, y = b;}
    void print(){printf("%lld %lld\n", x, y);}
};
Complex n;
ll ans[200];
void init(){
    n.x = read();
    n.y = read();
}
bool check(int x){
    return x == 0 || x == 1;
}
void work(){
    if((n.x & 1) != (n.y & 1)) ans[0] = 1, n.x--;
    if((n.x & 1) && (n.y & 1)) ans[1] = 1, n.x++, n.y--;
    ans[3] = n.x / 2; n.y -= n.x;
    ans[2] = n.y / (-2);
    ll t;
    for(int i = 2; i < 200; i++){
        if(check(ans[i]) && check(ans[i+1])) break;
        if(check(ans[i])) continue;
        if(ans[i] & 1) t = ans[i] - 1;
        else t = ans[i];
        ans[i+2] -= t / 2;
        ans[i] -= t;
        ans[i+1] -= t;
    }
    for(int i = 0; i < 200; i++)
        if(ans[i]) printf("%d\n", i);
}

int main(){
    freopen("erziehung.in", "r", stdin);
    freopen("erziehung.out", "w", stdout);
    init();
    work();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值