补题: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} z=gcd(xa1,xa2,,xan)y=zi=1n(xai)
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+ta1,x+ta2,,x+tan) y ′ = ∑ i = 1 n ( x − a i ) + n t z ′ y'=\frac{\sum_{i=1}^n (x-a_i)+nt}{z'} y=zi=1n(xai)+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,还得用个数据结构来优化


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值