补题:Codeforces Round #587 (Div. 3)

比赛入口


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}
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) y = i = 1 n ( x a i ) + n t z y'=\frac{\sum_{i=1}^n (x-a_i)+nt}{z'} 乍看一眼也证明不出 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,还得用个数据结构来优化


发布了28 篇原创文章 · 获赞 14 · 访问量 2952

猜你喜欢

转载自blog.csdn.net/qq_43408978/article/details/104088406