比赛入口
D Swords
做法:这道题关键是x就是数组中最大的值!
x最小的取值就是a数组中的最大值,假设x取的更大时结果更优。
乍看一眼也证明不出
,其实这里还有个特殊的地方,就是如果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,还得用个数据结构来优化