二次体

ijpc2で使用。めったに使わない。


struct Z{
	ll x,y;
	Z():x(0), y(0){}
	Z(ll _x):x(_x), y(0){}
	Z(ll _x, ll _y):x(_x), y(_y){}
	ll abs(){
		return x*x+y*y;
	}
};
Z& operator+=(Z&a, Z b){return a=Z(a.x+b.x, a.y+b.y);}
Z& operator-=(Z&a, Z b){return a=Z(a.x-b.x, a.y-b.y);}
Z& operator*=(Z&a, Z b){return a=Z( a.x*b.x-a.y*b.y, a.x*b.y+a.y*b.x );}
Z operator+(Z a, Z b){return a+=b;}
Z operator-(Z a, Z b){return a-=b;}
Z operator*(Z a, Z b){return a*=b;}
bool operator==(Z a, Z b){return a.x==b.x && a.y==b.y;}
bool operator!=(Z a, Z b){return a.x!=b.x || a.y!=b.y;}
 
Z& operator/=(Z&z1, Z z2){
	ll a=z1.x, b=z1.y, c=z2.x, d=z2.y;
	assert(c!=0 || d!=0);
	ll n1=a*c+b*d, n2=b*c-a*d;
	ll v1=n1/(c*c+d*d), v2=n2/(c*c+d*d);
	Z best_z;
	ll best_m=-1;
	for(ll u1=v1-1; u1<=v1+1; u1++){
		for(ll u2=v2-1; u2<=v2+1; u2++){
			Z z3(u1,u2);
			ll m=(z1-z2*z3).abs();
			if(best_m==-1 || m<best_m){
				best_z=z3;
				best_m=m;
			}
		}
	}
	assert(best_m<=z2.abs());
	return z1=best_z;
}
Z operator/(Z a, Z b){return a/=b;}
Z& operator%=(Z&z1, Z z2){
	Z z3=z1/z2;
	return z1=z1-z2*z3;
}
Z operator%(Z a, Z b){return a%=b;}
std::ostream& operator<<(std::ostream& os, Z z){
	return ( os << "(" << z.x << " + " << z.y << " * i )" );
}
 

使用例(ijpc2 porter)
#include "porter.h"
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cfloat>
#include <map>
#include <utility>
#include <set>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>
#include <sstream>
#include <complex>
#include <stack>
#include <queue>
#include <cstring>
#include <assert.h>
#include <sys/time.h>
#include <fstream>
 
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n)  FOR(i,0,n)
#define EACH(i,c) for(typeof((c).begin()) i=(c).begin(); i!=(c).end(); ++i)
#define EXIST(s,e) ((s).find(e)!=(s).end())
 
#define dump(x)  cerr << #x << " = " << (x) << endl;
#define debug(x) cerr << #x << " = " << (x) << " (L" << __LINE__ << ")" << " " << __FILE__ << endl;
#define deb(x) cerr << #x << " = " << (x) << " , ";
#define debl cerr << " (L" << __LINE__ << ")"<< endl;
 
 
#define clr(a) memset((a),0,sizeof(a))
#define nclr(a) memset((a),-1,sizeof(a))
#define pb push_back
#define INRANGE(x,s,e) ((s)<=(x) && (x)<(e))
#define MP(x,y) make_pair((x),(y))
 
double pi=3.14159265358979323846;
 
using namespace std;
static const double EPS = 1e-5;
typedef long long ll;
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<double> vd;
typedef vector<vd> vvd;
typedef vector<string> vs;
typedef unsigned int uint32_t; 
 
template<typename T> std::ostream& operator<<(std::ostream& os, const vector<T>& z){
	os << "[ ";
	REP(i,z.size())os << z[i] << ", " ;
	return ( os << "]" << endl);
}
 
template<typename T> std::ostream& operator<<(std::ostream& os, const set<T>& z){
	os << "set( "; 
	EACH(p,z)os << (*p) << ", " ;
	return ( os << ")" << endl);
}
 
template<typename T,typename U> std::ostream& operator<<(std::ostream& os, const map<T,U>& z){
	os << "{ "; 
	EACH(p,z)os << (p->first) << ": " << (p->second) << ", " ;
	return ( os << "}" << endl);
}
 
template<typename T,typename U> std::ostream& operator<<(std::ostream& os, const pair<T,U>& z){
	return ( os << "(" << z.first << ", " << z.second << ",)" );
}
 
struct Z{
	ll x,y;
	Z():x(0), y(0){}
	Z(ll _x):x(_x), y(0){}
	Z(ll _x, ll _y):x(_x), y(_y){}
	ll abs(){
		return x*x+y*y;
	}
};
Z& operator+=(Z&a, Z b){return a=Z(a.x+b.x, a.y+b.y);}
Z& operator-=(Z&a, Z b){return a=Z(a.x-b.x, a.y-b.y);}
Z& operator*=(Z&a, Z b){return a=Z( a.x*b.x-a.y*b.y, a.x*b.y+a.y*b.x );}
Z operator+(Z a, Z b){return a+=b;}
Z operator-(Z a, Z b){return a-=b;}
Z operator*(Z a, Z b){return a*=b;}
bool operator==(Z a, Z b){return a.x==b.x && a.y==b.y;}
bool operator!=(Z a, Z b){return a.x!=b.x || a.y!=b.y;}
 
Z& operator/=(Z&z1, Z z2){
	ll a=z1.x, b=z1.y, c=z2.x, d=z2.y;
	assert(c!=0 || d!=0);
	ll n1=a*c+b*d, n2=b*c-a*d;
	ll v1=n1/(c*c+d*d), v2=n2/(c*c+d*d);
	Z best_z;
	ll best_m=-1;
	for(ll u1=v1-1; u1<=v1+1; u1++){
		for(ll u2=v2-1; u2<=v2+1; u2++){
			Z z3(u1,u2);
			ll m=(z1-z2*z3).abs();
			if(best_m==-1 || m<best_m){
				best_z=z3;
				best_m=m;
			}
		}
	}
	assert(best_m<=z2.abs());
	return z1=best_z;
}
Z operator/(Z a, Z b){return a/=b;}
Z& operator%=(Z&z1, Z z2){
	Z z3=z1/z2;
	return z1=z1-z2*z3;
}
Z operator%(Z a, Z b){return a%=b;}
 
std::ostream& operator<<(std::ostream& os, Z z){
	return ( os << "(" << z.x << " + " << z.y << " * i )" );
}
 
Z extgcd(Z a, Z b, Z&x, Z& y){
	Z d=a;
	if(b!=Z()){
		d = extgcd(b, a%b, y, x);
		y-=(a/b)*x;
	}
	else{
		x=1;
		y=0;
	}
	return d;
}
 
Z m;
Z current;
void init(int E, int S){
	m=Z(E,S);
	//deb(m);
	current=Z();
}
int moveTo(int X, int Y, int A, int B){
	Z target(X,Y);
	Z a(A,B);
	Z b=target-current;
	//deb(a);deb(b);debl;
	current=target;
	if(a==Z(0,0)){
		if(b==Z(0,0))return 0;
		else return -1;
	}
	Z x, y;
	Z d=extgcd(a,m,x,y);
	assert(a*x+m*y==d);
	//debug(d);
	//debug(b/d);
	//debug(b%d);
	if(b%d!=Z(0,0))return -1;
	Z m0=m/d;
	Z ret=(x*(b/d))%m0;
	assert((a*ret-b)%m==0);
	ll mini=1LL<<60;
	//debug(ret);
	for(int x1=-5; x1<=5; x1++){
		for(int y1=-5; y1<=5; y1++){
			Z g=ret+Z(x1,y1)*m0;
			mini=min(mini, abs(g.x)+abs(g.y));
		}
	}
	return mini;
}
 

タグ:

+ タグ編集
  • タグ:
最終更新:2012年06月30日 09:23