\(\mathtt{Description}\)
给定 \(a,b\),求 $\max \gcd(a+k,b+k),k\in [-\min(a,b),+\infty] \cap \mathbb Z $
多组数据。
特殊规定:\(\gcd(0,x)=x\)
\(\mathtt{restrictions:}1\leq a,b\leq 10^{18}\)
\(\mathtt{Solution}\)
考虑更相减损术:\(\gcd(a,b) = \gcd(b,a-b)\quad(a \ge b)\)
有 \(\gcd(a+k,b+k)=\gcd(b+k,a-b)\)
注意到 \(a-b\) 是定值,所以只需要 \(b+k\) 是 \(a-b\) 的倍数即可。
注意特判。
时间复杂度:\(\mathcal O (T)\;(T\)为询问次数\()\)
\(\mathtt{Code}\)
void solve() {
in(a,b) ;
if (a == b) return out(' ',0,0),fastio::putc('\n'),void();
if (a < b) std::swap(a,b) ;
c = a - b ;
out(' ',c,min(b % c,c - b % c)) ;
fastio::putc('\n') ;
}
\(\text{B. Customising the Track}\)
\(\mathtt{Description}\)
给定长度为 \(n\) 的数列 \(a\),你可以进行无穷次如下操作:选择两个 \(i,j\in [1,n]\),使 \(a_i=a_i+1,a_j=a_j-1\)。
最小化
多测。
\(\mathtt{restrictions:}0\leq a_i\leq 10^9,1\le n,\sum n\le2\times 10^5\)
\(\mathtt{Solution}\)
注意到序列的值越平均,上述值就越小,所以我们可以将其赋值为平均数附近的数。
设 \(sum=\sum a_i,v = sum\%n\),则答案为 \(v\times(n-v)\)
即每个被赋成较小的平均数的值会产生被赋成较大的平均数的值的个数的贡献。
时间复杂度:\(\mathcal O(\sum n)\)
\(\mathtt{Code}\)
void solve() {
long long sum = 0;
in(n) ;
for (int i = 1; i <= n; ++i) {
long long x ;
in(x),sum += x ;
}
const long long value1 = sum % n,value2 = n - value1 ;
out('\n',value1 * value2) ;
}
\(\text{C. Need for Pink Slips}\)
\(\mathtt{Description}\)
#@@\(#@(\)@#\(#_\)*#\(_(#@_\)(_#@@!#
\(\mathtt{Solution}\)
没啥好说的,模拟就行,注意精度。
复杂度也很玄,大概是 \(\mathcal O\)(能过)
\(\mathtt{Code}\)
struct Elem {
long double v ;
Elem(long double v = 0) : v(v) {}
static constexpr long double eps = 1e-8 ;
friend Elem operator * (Elem a,Elem b) {
return Elem(a.v*b.v);
}
friend bool operator != (Elem a,Elem b) {
return fabs(a.v - b.v) > eps;
}
friend bool operator == (Elem a,Elem b) {
return fabs(a.v - b.v) <= eps;
}
friend bool operator <= (Elem a,Elem b) {
return (a.v - b.v) <= eps;
}
friend Elem operator + (Elem a,Elem b) {
return Elem(a.v+b.v);
}
friend Elem operator - (Elem a,Elem b) {
return Elem(a.v-b.v);
}
friend Elem operator / (Elem a,Elem b) {
return Elem(a.v/b.v);
}
};
int t ;
Elem a,b,c,v,ans;
void calc(int dep,Elem now,Elem a,Elem b,Elem c) {
ans = ans + dep * c * now ;
if (c == 1.0) return ;//if c == 1.0
if (a != -1.0) {//if a is legal
if (a <= v) {//if a is smaller than v
if (b == -1.0) calc(dep+1,1.0*now*a,-1.0,-1.0,1.0);
else calc(dep+1,1.0*now*a,-1.0,a/2+b,a/2+c);
}
else {
if (b == -1.0) calc(dep+1,1.0*now*a,a-v,-1.0,c+v);
else calc(dep+1,1.0*now*a,a-v,b+v/2,c+v/2);
}
}
if (b != -1.0) {
if (b <= v) {
if (a == -1.0) calc(dep+1,1.0*now*b,-1.0,-1.0,1.0);
else calc(dep+1,1.0*now*b,a+b/2,-1.0,b/2+c);
}
else {
if (a == -1.0) calc(dep+1,1.0*now*b,-1.0,b-v,c+v);
else calc(dep+1,1.0*now*b,a+v/2,b-v,c+v/2);
}
}
}
void solve() {
ans = 0,scanf("%Lf%Lf%Lf%Lf",&a.v,&b.v,&c.v,&v.v) ;
calc(1,1,a,b,c),printf("%.10Lf\n",ans.v);
}
\(\text{D. RPD and Rap Sheet }\)
\(\mathtt{Description}\)
交互题,交互库有一密码 \(z\)。
给定 \(n,k\),你可以询问 \(n\) 次,每次询问一个整数 \(y\),如果询问数与密码相同则结束,否则密码变为 \(z\oplus_k y\),你需要在 \(n\) 次询问内得到正确答案。
\(\mathtt{Solution}\)
有趣的构造题啊!
构造如下询问序列 \(q\):
\(q_0=0,\forall i \in [1,n) \quad q_i = i\oplus_k(i-1)\)