CF1487C Minimum Ties 题解
为什么题解里面都写得这么复杂啊……
提供一种极其简单的做法。
设非平局的场数为 \(a\),平局场数为 \(b\)。显然,所有人的得分和为 \(3a+2b=3(a+b)-b\)。
由题得 \(\dfrac{n(n+1)}2=a+b\)(即总场数为非平局场数加上平局场数),所以我们可以 \(O(1)\) 得出使得总得分能被 \(n\) 整除的 \(b\)。
既然得到了平局场数,随即得到每个人的分数。然后呢?只要分数大于等于 \(3\),就让他赢,否则:若分数大于 \(0\) 则本场平局,否则输。
因为 \(n\) 很小,所以每次询问的复杂度差不多是 \(O(n)\)。
具体看代码:
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(register int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(register int i=(a);i>=(b);--i)
#define read() Read<int>()
#define write Write<int>
#define writesp Writesp<int>
#define writeln Writeln<int>
template<typename T>
inline T Read()
{
bool f=0;T x=0;char ch;
do{ch=getchar();f|=(ch=='-');}while(!isdigit(ch));
do{x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}while(isdigit(ch));
return f?-x:x;
}
template<typename T>
inline void Write(T x)
{
if(x<0){putchar('-');write(-x);return;}
if(x>9)write(x/10);
putchar(x%10+48);
}
template<typename T> inline void Writeln(T x){Write(x);puts("");}
template<typename T> inline void Writesp(T x){Write(x);putchar(' ');}
int a[105];//记录每个人之前比赛的总得分
int main()
{
int t=read();
while(t--)
{
memset(a,0,sizeof a);
int n=read();
int tot=n*(n-1)/2;//比赛总场数
int tie=tot*3%n;//平局数量
int pts=tot*3/n;//每个人的分数
rep(i,1,n)
{
int q=pts-a[i];//当前剩余的得分
int cur=i+1;//当前对战的球队
while(q>=3)//赢
{
a[i]+=3;
writesp(1);
++cur;
q-=3;
}
while(q)//平
{
a[i]+=1;
a[cur]+=1;
--q;++cur;
writesp(0);
}
while(cur<=n)//输
{
a[cur]+=3;
writesp(-1);
++cur;
}
}
puts("");
}
return 0;
}
事实上,我怎么想都没有想到题解中 \(O(n^2)\) 和 \(O(n^3)\) 的做法。应该是我太菜了,或者这个做法是假的,数据水了。
我好菜啊。——ฅ(OωO)ฅ