1. 程式人生 > >2017中國大學生程式設計競賽-哈爾濱站

2017中國大學生程式設計競賽-哈爾濱站

大力施工......(10/13)剩下的三個題好像不太能寫啊?

A.Palindrome(hdu6230)

首先用Manacher處理出所有的迴文半徑,然後可以得到每個點覆蓋的範圍,問題轉換成了,有多少對點,滿足,i能覆蓋j而且j也能覆蓋i,我們按照迴文半徑從大到小進行排序,然後用線段樹進行維護,然後每次查詢當前點能覆蓋的範圍有多少點即可,更新答案,最後將該點更新到線段樹上。

程式碼:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=5e5+5;
char Ma[MAXN];
int Mp[MAXN];
void Manacher(int len)
{
	int l=len;
	Ma[0]='$';
	Ma[l]=0;
	int mx=0,id=0;
	for(int i=0;i<l;i++)
	{
		Mp[i]=mx>i?min(Mp[2*id-i],mx-i):1;
		while(Ma[i+Mp[i]]==Ma[i-Mp[i]])Mp[i]++;
		if(i+Mp[i]>mx)
		{
			mx=i+Mp[i];
			id=i;
		}
	}
}
struct node
{
	int id,r;
	node(int _id=0,int _r=0):id(_id),r(_r){}
	bool operator <(const node &a)const
	{
		return r>a.r;
	}
}sv[MAXN];
struct seg
{
	#define lson l,mid,rt<<1
	#define rson mid+1,r,rt<<1|1
	int sum[MAXN<<2];
	inline void push_up(int rt)
	{
		sum[rt]=sum[rt<<1]+sum[rt<<1|1];
	}
	void build(int l,int r,int rt)
	{
		sum[rt]=0;
		if(l==r)
			return ;
		int mid=(l+r)>>1;
		build(lson);
		build(rson);
	}
	void update(int pos,int val,int l,int r,int rt)
	{
		if(l==r)
		{
			sum[rt]=val;
			return ;
		}
		int mid=(l+r)>>1;
		if(pos<=mid)
			update(pos,val,lson);
		if(pos>mid)
			update(pos,val,rson);
		push_up(rt);
	}
	int query(int L,int R,int l,int r,int rt)
	{
		if(L<=l&&r<=R)
			return sum[rt];
		int ret=0;
		int mid=(l+r)>>1;
		if(L<=mid)
			ret+=query(L,R,lson);
		if(mid<R)
			ret+=query(L,R,rson);
		return ret;
	}
}se;
void solve()
{
	int len;
	ll ans=0;
	scanf("%s",Ma+1);
	len=strlen(Ma+1);
	Manacher(len+1);
	for(int i=1;i<=len;i++)
	{
		sv[i]=node(i,Mp[i]-1);
	}
	sort(sv+1,sv+1+len);
	se.build(1,len,1);
	for(int i=1;i<=len;i++)
	{
		int id=sv[i].id,r=sv[i].r;
		ans+=se.query(max(1,id-r),min(len,id+r),1,len,1);
		se.update(id,1,1,len,1);
	}
	printf("%lld\n",ans);
}
int main()
{
	//freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);
	int T;
	scanf("%d",&T);
	while(T--)
	{
		solve();
	}
	return 0;
}

B.K-th Number(hdu6231)

二分答案,統計有多少個區間的第k大的值大於等於我們二分的答案,如果區間數大於m,就提高下界繼續二分,否則降低上界。計數的時候可以採用雙指標。

程式碼:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=1e5+5;
int a[MAXN],HASH[MAXN],tot,n,k;
ll m;
vector<int> sv;
int getid(int x)
{
	int ret=lower_bound(HASH+1,HASH+1+tot,x)-HASH;
	return ret;
}
bool judge(int mid)
{
	ll ret=0;
	sv.clear();
	sv.push_back(0);
	for(int i=1;i<=n;i++)
	{
		if(a[i]>=mid)
		{
			sv.push_back(i);
		}
	}
	for(int i=0;i<sv.size();i++)
	{
		if(i<k)
			continue;
		ret+=(sv[i-k+1]-sv[i-k])*(n-sv[i]+1);
	}
	return ret>=m;
}
void solve()
{
	tot=0;
	scanf("%d%d%lld",&n,&k,&m);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		HASH[++tot]=a[i];
	}
	sort(HASH+1,HASH+1+tot);
	tot=unique(HASH+1,HASH+1+tot)-HASH-1;
	for(int i=1;i<=n;i++)
	{
		a[i]=getid(a[i]);
	}
	int l=1,r=tot;
	int ans=0;
	while(l<=r)
	{
		int mid=(l+r)>>1;
		if(judge(mid))
		{
			l=mid+1;
			ans=mid;
		}
		else
		{
			r=mid-1;
		}
	}
	printf("%d\n",HASH[ans]);
}
int main()
{
	//freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);
	int T;
	scanf("%d",&T);
	while(T--)
	{
		solve();
	}
	return 0;
}

C.Confliction(hdu6232)

將運動轉換為B對於A的相對運動,然後答案就是經過次數最多的那個點,然後離散化時間和座標,進行差分求解出現的次數最多的那個點就好了,不過挺難寫的啊?

程式碼:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=2e5+5;
int Na,Nb,Ac[MAXN],Bc[MAXN];
ll At[MAXN],Bt[MAXN],Hash[MAXN*2],sz;
vector<tuple<ll,int,ll> > seg;
void solve()
{
	ll pos=0;
	seg.clear();
	scanf("%d",&Na);
	for(int i=1;i<=Na;i++)
	{
		scanf("%d%lld",&Ac[i],&At[i]);
		if(At[i]==0) i--,Na--;
	}
	scanf("%d",&Nb);
	for(int i=1;i<=Nb;i++)
	{
		scanf("%d%lld",&Bc[i],&Bt[i]);
		if(Bt[i]==0) i--,Nb--;
	}
	sz=0;
	for(int i=1;i<=Na;i++)
	{
		At[i]+=At[i-1];Hash[++sz]=At[i];
	}
	for(int i=1;i<=Nb;i++)
	{
		Bt[i]+=Bt[i-1];Hash[++sz]=Bt[i];
	}
	sort(Hash+1,Hash+1+sz);
	sz=unique(Hash+1,Hash+1+sz)-Hash-1;
	seg.push_back(make_tuple(0,3,1));
	seg.push_back(make_tuple(1,3,-1));
	for(int i=1,pa=1,pb=1;i<=sz;i++)
	{
		while(At[pa]<Hash[i]) pa++;
		while(Bt[pb]<Hash[i]) pb++;
		ll t=Hash[i]-Hash[i-1];
		ll delta=Bc[pb]-Ac[pa];
		if(delta==0)
		{
			seg.push_back(make_tuple(pos,3,t));
			seg.push_back(make_tuple(pos+1,3,-t));
		}
		else
		{
			ll l=pos+delta,r=pos+t*delta;
			if(l>r) swap(l,r);
			int k=3;
			if(delta==2||delta==-2) k=(l&1)?1:2;
			seg.push_back(make_tuple(l,k,1));
			seg.push_back(make_tuple(r+1,k,-1));
		}
		pos+=t*delta;
	}
	sort(seg.begin(),seg.end());
	ll mx=0,cnt0=0,cnt1=0;
	for(int i=0,j=0;i<seg.size();i=j)
	{
		while(j<seg.size()&&get<0>(seg[j])==get<0>(seg[i]))
		{
			if(get<1>(seg[j])&1) cnt1+=get<2>(seg[j]);
			if(get<1>(seg[j])&2) cnt0+=get<2>(seg[j]);
			j++;
		}
		if(get<0>(seg[i])&1) mx=max(mx,cnt1);
		else mx=max(mx,cnt0);
	}
	printf("%lld\n",mx);
}
int main()
{
	//freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);
	int T;
	scanf("%d",&T);
	while(T--)
	{
		solve();
	}
	return 0;
}

D.X-Men(hdu6233)

這可能是本場比賽第二簡單的題目???現場榜被帶歪了啊???其實理性分析一下,可以發現,每次最遠的兩個人的距離一定會減少2,所以直接直徑除二向下取整數就好了。

程式碼:

#include<bits/stdc++.h>
using namespace std;
const int MAXN=1005;
struct edge
{
	int to,nxt;
}E[MAXN*2];
int head[MAXN],tot,root,mx;
bool book[MAXN];
void addedge(int u,int v)
{
	E[tot].to=v;E[tot].nxt=head[u];head[u]=tot++;
	E[tot].to=u;E[tot].nxt=head[v];head[v]=tot++;
}
void init(int n)
{
	tot=0;
	memset(book,0,sizeof(book));
	for(int i=1;i<=n;i++)
	{
		head[i]=-1;
	}
}
void dfs(int now,int fa,int dp)
{
	if(book[now]&&dp>mx)
	{
		mx=dp;
		root=now;
	}
	for(int i=head[now];~i;i=E[i].nxt)
	{
		int v=E[i].to;
		if(v==fa)
			continue;
		dfs(v,now,dp+1);
	}
}
void solve()
{
	int n,m;
	scanf("%d%d",&n,&m);
	init(n);
	for(int i=1;i<=m;i++)
	{
		int x;
		scanf("%d",&x);
		book[x]=true;
		root=x;
	}
	for(int i=1;i<n;i++)
	{
		int u,v;
		scanf("%d%d",&u,&v);
		addedge(u,v);
	}
	mx=0;
	dfs(root,0,0);
	mx=0;
	dfs(root,0,0);
	printf("%d.00\n",mx/2);
}
int main()
{
	//freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);
	int T;
	scanf("%d",&T);
	while(T--)
	{
		solve();
	}
	return 0;
}

F.Permutation(hdu6235)

水題,隨便構造一下就好。。。

程式碼:

#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+5;
int a[MAXN];
void solve()
{
	int n;
	scanf("%d",&n);
	int cnt=1;
	for(int i=1;i<=n;i+=2)
	{
		a[i]=cnt++;
	}
	for(int i=2;i<=n;i+=2)
	{
		a[i]=cnt++;
	}
	printf("%d",a[1]);
	for(int i=2;i<=n;i++)
	{
		printf(" %d",a[i]);
	}
	printf("\n");
}

int main()
{
	//freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);
	int T;
	scanf("%d",&T);
	while(T--)
	{
		solve();
	}
	return 0;
}

H.A Simple Stone Game(hdu6237)

首先我們將陣列a的所有值加起來得到sum,然後求sum的所有的素因子,然後直接列舉所有的素因子就好了,設我們當前的素因子為p,我們對a陣列所有的值對p取模,然後按照從大到小排序,然後貪心的移動就好了(每次把最大的填到p),存素因子的陣列不用long long wa的莫名其妙?

程式碼:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=1e5+5;
int a[MAXN],b[MAXN];
ll pre[MAXN];
vector<ll> sv;
void Prime(ll x)
{
	sv.clear();
	for(ll i=2;i*i<=x;i++)
	{
		if(x%i==0) sv.push_back(i);
		while(x%i==0) x/=i;
	}
	if(x!=1) sv.push_back(x);
}
void solve()
{
	int n;
	ll sum=0,ans=1e18;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		sum+=a[i];
	}
	Prime(sum);
	for(int i=0;i<sv.size();i++)
	{
		ll p=sv[i],tot=0;
		for(int j=1;j<=n;j++)
			b[j]=a[j]%p;
		sort(b+1,b+1+n);
		pre[0]=0;
		for(int j=1;j<=n;j++)
			pre[j]=pre[j-1]+b[j];
		for(int j=n;j>=1;j--)
		{
			if(tot==pre[j]) break;
			tot+=p-b[j];
		}
		ans=min(ans,tot);
	}
	printf("%lld\n",ans);
}
int main()
{
	//freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);
	int T;
	scanf("%d",&T);
	while(T--)
	{
		solve();
	}
	return 0;
}

J.Interview(hdu6239)

我們隊猜出了個線性的式子...可能正解要用到i^k (k<=3)的求和公式,不知道我們這個式子為啥是對的...可能最後化簡出來就是我們的式子吧,具體看程式碼

程式碼:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MOD=1e9+7;
ll qpow(ll a,ll b)
{
	ll ret=1;
	while(b)
	{
		if(b&1)
		{
			ret*=a;
			ret%=MOD;
		}
		a=(a*a)%MOD;
		b>>=1;
	}
	return ret;
}
int main()
{
	//freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);
	int T;
	scanf("%d",&T);
	while(T--)
	{
		int n,d;
		scanf("%d%d",&n,&d);
		if(d==1)
			printf("%lld\n",(2LL*n+4LL)%MOD*qpow(8,MOD-2)%MOD);
		else
			printf("%lld\n",(3LL*n+6LL)%MOD*qpow(8,MOD-2)%MOD);
	}
	return 0;
}

K.Server(hdu6240)

分數規劃經典問題哦,感覺自己分數規劃還是掌握的不太好啊,看了zzq神犇的部落格重新回憶了一下,發現自己為啥在求最大值啊?首先肯定是要二分答案的,然後,就是轉化為最小值是否大於0的問題,對於最小值的問題,可以直接進行dp,我們首先按照右端點進行排序,對於將所有花費變為a-mid*b,然後對於所有花費為負的線段,我們一定會選,所以我們首先把花費為負的線段花費變成0,然後進行dp,最後將所有的為負的花費的權值加入,即可得到最小花費,dp的過程要用線段樹來維護。好像跑最短路也可以?

程式碼:

#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+5;
const double INF=1e9;
const double eps=1e-6; 
int n,t;
struct monitor
{
	int s,t,a,b;
	double val;
	bool operator < (const monitor &o)const
	{
		return t<o.t;
	}
}sv[MAXN];
struct seg
{
	#define lson l,mid,rt<<1
	#define rson mid+1,r,rt<<1|1
	double mi[MAXN<<2];
	void push_up(int rt)
	{
		mi[rt]=min(mi[rt<<1],mi[rt<<1|1]);
	}
	void build(int l,int r,int rt)
	{
		mi[rt]=INF;
		if(l==r)
			return ;
		int mid=(l+r)>>1;
		build(lson);
		build(rson);
	}
	void update(int pos,double val,int l,int r,int rt)
	{
		if(l==r)
		{
			mi[rt]=min(val,mi[rt]);
			return ;
		}
		int mid=(l+r)>>1;
		if(mid>=pos)
			update(pos,val,lson);
		if(mid<pos)
			update(pos,val,rson);
		push_up(rt);
	}
	double query(int L,int R,int l,int r,int rt)
	{
		if(L<=l&&r<=R)
		{
			return mi[rt];
		}
		int mid=(l+r)>>1;
		double ret=INF;
		if(L<=mid)
			ret=min(ret,query(L,R,lson));
		if(mid<R)
			ret=min(ret,query(L,R,rson));
		return ret;
	}
}se;
double judge(double mid)
{
	for(int i=1;i<=n;i++)
	{
		sv[i].val=sv[i].a-mid*sv[i].b;
	}
	se.build(0,t,1);
	se.update(0,0,0,t,1);
	double sum=0;
	for(int i=1;i<=n;i++)
	{
		double val=se.query(sv[i].s-1,sv[i].t,0,t,1);
		double add=sv[i].val;
		if(add<0)
			sum+=add,add=0;
		se.update(sv[i].t,val+add,0,t,1);
	}
	double val=se.query(t,t,0,t,1);
	return val+sum;
}
void solve()
{
	scanf("%d%d",&n,&t);
	for(int i=1;i<=n;i++)
	{
		scanf("%d%d%d%d",&sv[i].s,&sv[i].t,&sv[i].a,&sv[i].b);
	}
	sort(sv+1,sv+1+n);
	int cnt=25;
	double ans=INF;
	double l=0,r=1005;
	while(cnt--)
	{
		double mid=(l+r)/2;
		double res=judge(mid);
		if(res>0)
		{
			l=mid;
			ans=mid;
		}
		else
		{
			r=mid;
		}
	}
	printf("%.3lf\n",ans);
}
int main()
{
	//freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);
	int T;
	scanf("%d",&T);
	while(T--)
	{
		solve();
	}
	return 0;
}

L.Color a Tree(hdu6241)

二分答案,然後將子樹外的問題轉換成子樹內最多有多少點的問題,然後從葉子開始合併區間,判斷每個節點是否可行,最後還要判斷二分的值是否在根的可行區間當中。

程式碼:

#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+5;
struct edge
{
	int v,nxt;
}E[MAXN*2];
struct node
{
	int up,down;
}tr[MAXN];
struct lim
{
	int id,num;
}A[MAXN],B[MAXN];
int head[MAXN],sz[MAXN],tot,n,na,nb;
bool flag;
void init()
{
	tot=0;
	memset(head,-1,sizeof(head));
}
void addedge(int u,int v)
{
	E[tot].v=v;E[tot].nxt=head[u];head[u]=tot++;
	E[tot].v=u;E[tot].nxt=head[v];head[v]=tot++;
}
void getlim(int mid)
{
	for(int i=1;i<=n;i++)
	{
		tr[i].down=0,tr[i].up=sz[i];
	}
	for(int i=1;i<=na;i++)
	{
		int id=A[i].id,num=A[i].num;
		tr[id].down=max(tr[id].down,num);
	}
	for(int i=1;i<=nb;i++)
	{
		int id=B[i].id,num=B[i].num;
		tr[id].up=min(tr[id].up,mid-num);
	}
	for(int i=1;i<=n&&flag;i++)
	{
		if(tr[i].down>tr[i].up)
			flag=false;
	}
}
void dfssz(int now,int fa)
{
	sz[now]=1;
	for(int i=head[now];~i;i=E[i].nxt)
	{
		int v=E[i].v;
		if(v==fa)
			continue;
		dfssz(v,now);
		sz[now]+=sz[v];
	}
}
void dfslim(int now,int fa)
{
	int down=0,up=0;
	for(int i=head[now];(~i)&&flag;i=E[i].nxt)
	{
		int v=E[i].v;
		if(v==fa)
			continue;
		dfslim(v,now);
		down+=tr[v].down,up+=tr[v].up;
	}
	tr[now].down=max(tr[now].down,down);
	tr[now].up=min(tr[now].up,up+1);
	//printf("%d:%d %d\n",now,tr[now].down,tr[now].up);
	if(tr[now].down>tr[now].up)
		flag=false;
}
void judge(int mid)
{
	getlim(mid);
	dfslim(1,0);
	if(!(tr[1].down<=mid&&mid<=tr[1].up))
		flag=false;
}
void solve()
{
	init();
	scanf("%d",&n);
	for(int i=1;i<n;i++)
	{
		int u,v;
		scanf("%d%d",&u,&v);
		addedge(u,v);
	}
	dfssz(1,0);
	scanf("%d",&na);
	for(int i=1;i<=na;i++)
	{
		scanf("%d%d",&A[i].id,&A[i].num);
	}
	scanf("%d",&nb);
	for(int i=1;i<=nb;i++)
	{
		scanf("%d%d",&B[i].id,&B[i].num);
	}
	int l=0,r=n;
	int ans=-1;
	while(l<=r)
	{
		flag=true;
		int mid=(l+r)>>1;
		judge(mid);
		if(flag)
		{
			r=mid-1;
			ans=mid;
		}
		else
		{
			l=mid+1;
		}
	}
	printf("%d\n",ans);
}
int main()
{
	//freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);
	int T;
	scanf("%d",&T);
	while(T--)
	{
		solve();
	}
	return 0;
}

M.Geometry Problem(hdu6242)

理性分析一下,就會發現,隨機三個點然後求圓心即可,期望是8次就能隨中。

程式碼:

#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+5;
const double eps=1e-6;
int sgn(double x) 
{
	if(fabs(x)<eps)return 0;
	if(x<0)return -1;
	else return 1;
}
struct Point
{
	double x,y;
	Point(double _x=0,double _y=0):x(_x),y(_y){}
	double operator ^ (const Point &b)const//叉積
	{
		return x*b.y-y*b.x;
	}
	Point operator - (const Point &b)const
	{
		return Point(x-b.x,y-b.y); 
	}
}P[MAXN];
struct Traingle
{
	Point p[3];
	Traingle(){}
	Traingle(Point a,Point b,Point c)
	{
		p[0]=a;p[1]=b;p[2]=c;
	}
};
struct Circle
{
	Point center;
	double r;
};
double Dis(Point a,Point b)
{
	double dx=a.x-b.x;
	double dy=a.y-b.y;
	return sqrt(dx*dx+dy*dy);
}
double Area(Traingle T)
{
	Point A=T.p[0]-T.p[1];
	Point B=T.p[1]-T.p[2];
	return (A^B)/2;
}
Circle CircumCircle(Traingle T)
{
	Circle ret;
	double a,b,c,c1,c2;
	double xA,yA,xB,yB,xC,yC;
	a=Dis(T.p[0],T.p[1]);
	b=Dis(T.p[1],T.p[2]);
	c=Dis(T.p[2],T.p[0]);
	ret.r=(a*b*c)/(Area(T)*4.0);
	xA=T.p[0].x;yA=T.p[0].y;
	xB=T.p[1].x;yB=T.p[1].y;
	xC=T.p[2].x;yC=T.p[2].y;
	c1=(xA*xA+yA*yA-xB*xB-yB*yB)/2;
	c2=(xA*xA+yA*yA-xC*xC-yC*yC)/2;
	ret.center.x=(c1*(yA-yC)-c2*(yA-yB))/((xA-xB)*(yA-yC)-(xA-xC)*(yA-yB));
	ret.center.y=(c1*(xA-xC)-c2*(xA-xB))/((yA-yB)*(xA-xC)-(yA-yC)*(xA-xB));
	return ret;
}
void gettwo(Point a,Point b)
{
	double x=(a.x+b.x)/2;
	double y=(a.y+b.y)/2;
	printf("%lf %lf %lf\n",x,y,Dis(a,Point(x,y)));
}
int id[3],n;
void getid()
{
	id[0]=rand()%n+1;
	id[1]=rand()%n+1;
	id[2]=rand()%n+1;
	while(id[1]==id[0])
		id[1]=rand()%n+1;
	while(id[2]==id[0]||id[2]==id[1])
		id[2]=rand()%n+1;
}
int judge(Point a,Point b,Point c)
{
	Point A=a-b;
	Point B=c-b;
	return sgn(A^B);
}
void solve()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%lf%lf",&P[i].x,&P[i].y);
	}
	if(n==1)
	{
		printf("%lf %lf %d\n",P[1].x-1,P[1].y,1);
		return ;
	}
	if(n>=2&&n<=4)
	{
		gettwo(P[1],P[2]);
		return ;
	}
	while(1)
	{
		memset(id,0,sizeof(id));
		getid();
		if(!judge(P[id[0]],P[id[1]],P[id[2]]))
			continue;
		Circle res=CircumCircle(Traingle(P[id[0]],P[id[1]],P[id[2]]));
		int cnt=0;
		for(int i=1;i<=n;i++)
		{
			double dis=Dis(P[i],res.center);
			if(sgn(dis-res.r)==0)
				cnt++;
		}
		if(cnt>=(n+1)/2)
		{
			printf("%lf %lf %lf\n",res.center.x,res.center.y,res.r);
			return ;
		}
	}
}
int main()
{
	//freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);
	int T;
	srand(0);
	scanf("%d",&T);
	while(T--)
	{
		solve();
	}
	return 0;
}