Description
B 君最近听说了一个很惊人的性质,设
p=1+i
,对于每个高斯整数
x+yi
,我们都可以找到一个非负整数集合S 满足
∑k∈Spk=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(pn−1+pn−2)
证明很简单:
−2(pn−1+pn−2)====−2[pn−2×(p+1)]pn−2×(−2i)pn−2×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;
}