ural 1275. Knights of the Round Table

\(n\) 个围着圆桌,其中第 \(i\) 个人有 \(a_i\) 个盘子,服务员每个可以给相邻为 \(k\) 的两个人各自带来/带走一个盘子 , 需要求出最少的方案数使得最后每个人都有 \(F\) 个盘子 .

\(1\leq n\leq 1000,1\leq k\leq n-1,0\leq a_i,F\leq1000\)

考虑操作 \((i-k,i)\) 的操作数量为 \(x_i\) .

\(x_0+x_k=F-a_0\)

\(x_1+x_{k+1}=F-a_1\)

\(\cdots\)

\(x_{n-1}+x_{n-1+k}=F-x_{n-1}\)

这里的下标都是模 \(n\) 后的 .

此时有 \(n\) 个方程,有 \(n\) 个未知量,但是还是需要分成几种情况讨论 .

第一种特殊情况是 \(2k=n\),此时需要 \(a_i=a_{i+k}\) . 操作很好构造 .

第二种操作是有 \(m\) 个方程,\(m\) 个未知量,可以设其中一个量为 \(x\) 其他的所有的位置量都可以用 \(x\) 表示,最后绕了一圈后可以得到一个表示 \(b+x\) 或者 \(b-x\) .

如果 \(b-x=x\) ,那么 \(b\) 是偶数,其他的值可以直接求出 .

如果 \(b+x=x\) ,那么 \(b=0\) ,对于每个 \(x_i=x+b_i\ /\ x_i=-x+b_i\) . 其中 \(b_i\) 或者 \(-b_i\) 就是临界点,可以 \(O(n)\) 处理出最小值 .

时间复杂度 : \(O(n+ans)\) .

空间复杂度 : \(O(n)\)

首先要先输出 + 再输出 - ,其次,输出操作的时候不能用 \(\rm{vector}\) 保存,会超出空间限制 .

code

#include<bits/stdc++.h>
using namespace std;
char in[100005];
int iiter=0,llen=0;
inline char get(){
	if(iiter==llen)llen=fread(in,1,100000,stdin),iiter=0;
	if(llen==0)return EOF;
	return in[iiter++];
}
inline long long rd(){
	char ch=get();while(ch<'0'||ch>'9')ch=get();
	long long res=0;while(ch>='0'&&ch<='9')res=(res<<3)+(res<<1)+ch-'0',ch=get();
	return res;
}
inline void pr(long long res){
	if(res==0){putchar('0');return;}
	static int out[20];int len=0;
	while(res)out[len++]=res%10,res/=10;
	for(int i=len-1;i>=0;i--)putchar(out[i]+'0');
}
#define pb push_back
#define mp make_pair
#define fi first
#define se second
const int N=1e3+10;
int n,k,F;
int a[N];
class node{public:int k,b;}eq[N];
vector<int>v;
bool ok[N];
int ans[N];
inline void print(){
	int res=0;
	for(int i=0;i<n;i++)res+=abs(ans[i]);
	pr(res);putchar('\n');
	for(int i=0;i<n;i++){
		if(ans[i]<=0)continue;
		for(int j=0;j<ans[i];j++){
			pr((i-k+n)%n+1);putchar(' ');
			pr(i+1);putchar(' ');
			putchar('+');putchar('\n');
		}
	}
	for(int i=0;i<n;i++){
		if(ans[i]>=0)continue;
		for(int j=0;j<-ans[i];j++){
			pr((i-k+n)%n+1);putchar(' ');
			pr(i+1);putchar(' ');
			putchar('-');putchar('\n');
		} 
	}
}
void work_special(){
	for(int i=0;i<n;i++){
		if(F-a[i]!=F-a[(i+k)%n]){
			puts("-1");
			return;
		}
	}
	for(int i=0;i<n/2;i++)ans[i]=F-a[i];
	print();
}
void dfs(int id){
	ok[id]=true;
	v.pb(id);
	if(!ok[(id+k)%n]){
		eq[(id+k)%n]=(node){-eq[id].k,F-a[id]-eq[id].b};
		dfs((id+k)%n);
	}
}
inline bool cmp(const node&A,const node&B){
	return (A.k<0?A.b:-A.b)<(B.k<0?B.b:-B.b);
}
void solv1(vector<int>v){
	vector<node>tmp;
	for(int i=0;i<(int)v.size();i++)tmp.pb((node){eq[v[i]].k,eq[v[i]].b});
	sort(tmp.begin(),tmp.end(),cmp);
	int sk=0,sb=0;
	for(int i=0;i<(int)tmp.size();i++){
		if(tmp[i].k<0)sk+=tmp[i].k,sb+=tmp[i].b;
		else sk-=tmp[i].k,sb-=tmp[i].b;
	}
	int mn=tmp[0].k<0?tmp[0].b:-tmp[0].b,res=sk*mn+sb;
	for(int i=0;i+1<(int)tmp.size();i++){
		sk+=2;sb+=tmp[i].k<0?-2*tmp[i].b:2*tmp[i].b;
		int l=(tmp[i].k<0?tmp[i].b:-tmp[i].b),r=(tmp[i+1].k<0?tmp[i+1].b:-tmp[i+1].b);
		if(sk<0&&sk*r+sb<res)res=sk*r+sb,mn=r;
		if(sk>0&&sk*l+sb<res)res=sk*l+sb,mn=l;
		if(sk==0&&sb<res)res=sb,mn=l;
	}
	sk+=2;sb+=tmp.back().k<0?-2*tmp.back().b:2*tmp.back().b;
	int lstv=tmp.back().k<0?tmp.back().b:-tmp.back().b;
	if(sk*lstv+sb<res)res=sk*lstv+sb,mn=lstv;
	for(int i=0;i<(int)v.size();i++)ans[v[i]]=eq[v[i]].k*mn+eq[v[i]].b;
}
void solv2(vector<int>v,int x){
	for(int i=0;i<(int)v.size();i++)ans[v[i]]=eq[v[i]].k*x+eq[v[i]].b;
}
bool work(vector<int>v){
	node tmp=(node){-eq[v.back()].k,F-a[v.back()]-eq[v.back()].b};
	if(tmp.k==eq[v[0]].k){
		if(tmp.b!=0){
			puts("-1");
			return false;
		}
		solv1(v);
		return true;
	}else{
		if(tmp.b&1){
			puts("-1");
			return false;
		}
		solv2(v,tmp.b/2);
		return true;
	}
}
int main(){
	n=rd();k=rd();F=rd();
	for(int i=0;i<n;i++)a[i]=rd();
	if(k*2==n){
		work_special();
		return 0;
	}
	for(int i=0;i<n;i++){
		if(ok[i])continue;
		v.clear();
		eq[i]=(node){1,0};
		dfs(i);
		if(!work(v))return 0;
	}
	print();
	return 0;
}
posted @ 2022-02-05 21:10  xyangh  阅读(77)  评论(0)    收藏  举报