比赛入口
D Swords
做法:这道题关键是x就是数组中最大的值!
z
=
g
c
d
(
x
−
a
1
,
x
−
a
2
,
…
,
x
−
a
n
)
,
y
=
∑
i
=
1
n
(
x
−
a
i
)
z
z = gcd(x-a_1, x-a_2,\ldots,x-a_n),y=\frac{\sum_{i=1}^n (x-a_i)}{z}
z=gcd(x−a1,x−a2,…,x−an),y=z∑i=1n(x−ai)
x最小的取值就是a数组中的最大值,假设x取的更大时结果更优。
z
′
=
g
c
d
(
x
+
t
−
a
1
,
x
+
t
−
a
2
,
…
,
x
+
t
−
a
n
)
z' = gcd(x+t-a_1, x+t-a_2,\ldots,x+t-a_n)
z′=gcd(x+t−a1,x+t−a2,…,x+t−an)
y
′
=
∑
i
=
1
n
(
x
−
a
i
)
+
n
t
z
′
y'=\frac{\sum_{i=1}^n (x-a_i)+nt}{z'}
y′=z′∑i=1n(x−ai)+nt乍看一眼也证明不出
y
′
>
=
y
y'>=y
y′>=y,其实这里还有个特殊的地方,就是如果x是数组最大值,这时候差值中就会有一个0出现,这时候的结果就是其他非0元素的最大公约数,但是!如果这个0变成了t,是会给y增加负担的,于是,菜鸡的一场头脑风暴在这里变成了一道水题。
代码:
#include<bits/stdc++.h>
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define lson rt<<1, l, mid
#define rson rt<<1|1, mid+1, r
using namespace std;
typedef long long LL;
typedef pair<LL, int> pli;
typedef pair<int, int> pii;
typedef pair<LL, LL> pll;
typedef pair<double, double> pdd;
typedef map<char, int> mci;
typedef map<string, int> msi;
template<class T>
void read(T &res) {
int f = 1; res = 0;
char c = getchar();
while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); }
while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); }
res *= f;
}
const int N = 2e5+5;
LL a[N];
int main() {
int n; read(n);
LL Max = -1, sum = 0;
for(int i = 0; i < n; ++i) {
read(a[i]);
Max = max(Max, a[i]);
sum += a[i];
}
LL ans1, ans2 = 0;
for(int i = 0; i < n; ++i) {
ans2 = __gcd(ans2, Max-a[i]);
}
ans1 = (Max * n - sum) / ans2;
printf("%lld %lld\n", ans1, ans2);
return 0;
}
E2 Numerical Sequence (hard version)
做法:具体做法是二分,整个序列是一个大段,每个数字是一个小段,对于大段就二分找,对于小段用了一个公式(雾x10086)迭代…贴一份最精简的代码…
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll check(ll n,bool c) {
ll x=0,y=1;
while(n-y+1>=0) {
if(c)
x+=((n-y+1)*(n-y+2))/2;
else
x+=(n-y+1);
if(x>1e18)
return x;
y*=10;
}
return x;
}
int main() {
int q;
cin >> q;
while(q--) {
ll k, c = 2;
cin >> k;
k --;
char a[100];
while(c--) {
ll l=0,r=1e9;
while(l!=r) {
ll mid=(l+r)/2;
if(mid==l)
mid++;
if(check(mid,c)>k)
r=mid-1;
else
l=mid;
}
k-=check(l,c),sprintf(a,"%d",(int)l+1);
}
cout << a[k] << endl;
}
return 0;
}
F Wi-Fi
做法:这题的做法是dp,还得用个数据结构来优化