1. 程式人生 > >test20181017 B君的第一題

test20181017 B君的第一題

題意


分析

考場做法

對p的冪打表發現,我們一定可以把x和y的二進位制位從低到高依次調整成0。

具體而言,從0次冪開始每兩個分為一組a,b,那麼0,a,b,a+b組合中的一種可以將x,y的對應二進位制位都調整成0。

然後模擬一下就行了。

時間複雜度\(O(\log |x| + \log |y|)\)

#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<string>
#include<vector>
#include<list>
#include<deque>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<complex>
#define rg register
#define il inline
#define co const
#pragma GCC optimize ("O0")
using namespace std;
template<class T> il T read(T&x)
{
    T data=0;
    int w=1;
    char ch=getchar();
    while(!isdigit(ch))
    {
        if(ch=='-')
            w=-1;
        ch=getchar();
    }
    while(isdigit(ch))
        data=10*data+ch-'0',ch=getchar();
    return x=data*w;
}
typedef long long ll;
const int INF=0x7fffffff;
const complex<ll>p(-1,-1);

const int MAXN=1000;
int S[MAXN],cnt;

int main()
{
  freopen("guangzhou.in","r",stdin);
  freopen("guangzhou.out","w",stdout);
    ll x,y;
    read(x);read(y);
    complex<ll>a(1,0),b(-1,-1),t;
    for(int i = 0;x || y;++i,(a *= p) *= p,(b *= p) *= p)
    {
//      cerr<<"i="<<i<<endl;
//      cerr<<"a="<<a<<" b="<<b<<endl;
        t = 0;
        if( (x & (1LL << i)) == (t.real() & (1LL << i)) && (y & (1LL << i)) == (t.imag() & (1LL << i)) )
        {
//          cerr<<" case 1"<<endl;
            continue;
        }
        t = a;
        if( (x & (1LL << i)) == (t.real() & (1LL << i)) && (y & (1LL << i)) == (t.imag() & (1LL << i)) )
        {
//          cerr<<" case 2"<<endl;
            x -= t.real() ,y -= t.imag();
            S[++cnt] = 2 * i;
            continue;
        }
        t = b;
        if( (x & (1LL << i)) == (t.real() & (1LL << i)) && (y & (1LL << i)) == (t.imag() & (1LL << i)) )
        {
//          cerr<<" case 3"<<endl;
            x -= t.real() ,y -= t.imag();
            S[++cnt] = 2 * i + 1;
            continue;
        }
        t = a + b;
        if( (x & (1LL << i)) == (t.real() & (1LL << i)) && (y & (1LL << i)) == (t.imag() & (1LL << i)) )
        {
//          cerr<<" case 4"<<endl;
            x -= t.real() ,y -= t.imag();
            S[++cnt] = 2 * i;
            S[++cnt] = 2 * i + 1;
            continue;
        }
    }
    printf("%d\n",cnt);
    for(int i=1;i<=cnt;++i)
    {
        printf("%d\n",S[i]);
    }
//  fclose(stdin);
//  fclose(stdout);
    return 0;
}

標解

跟冬令營2017億兆京垓 (Radixphi)這道題有關。

像確定二進位制一樣,每次右移,然後判斷最後一位的奇偶,這題可以每次/p,然後判斷實部和虛部的和的奇偶。

高斯整數一定能表示成\(-1 \pm i\)進位制的形式,這是B君翻維基百科上翻到的。然後就被出成題了。

時間複雜度\(O(\log |x| + \log |y|)\)

#include <bits/stdc++.h>
using namespace std;
complex<long long> n, p, u;
long long x, y;
int a[200], c, i;
int main() {
    freopen("guangzhou.in", "r", stdin);
    freopen("guangzhou.out", "w", stdout);
    cin >> x >> y;
    n = complex<long long>(x, y);
    p = complex<long long>(-1, -1);
    while (n != complex<long long>(0, 0)) {
        if ((n.real() + n.imag()) % 2 != 0) {
            a[c++] = i;
            n -= complex<long long>(1, 0);
        }
        n /= p;
        i++;
    }
    printf("%d\n", c);
    for (int i = 0; i < c; i++) {
        printf("%d\n", a[i]);
    }
    return 0;
}