2020CCPC绵阳站部分题解

D题

二分轮次,每个小于x的人都要补充到x才能撑过x轮。

#include<bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
#define sz(x)  (int)x.size()
#define cl(x)  x.clear()
#define all(x)  x.begin() , x.end()
#define rep(i , x , n)  for(int i = x ; i <= n ; i ++)
#define per(i , n , x)  for(int i = n ; i >= x ; i --)
#define mem0(x)  memset(x , 0 , sizeof(x))
#define mem_1(x)  memset(x , -1 , sizeof(x))
#define mem_inf(x)  memset(x , 0x3f , sizeof(x))
#define debug(x)  cerr << #x << " = " << x << '\n'
#define ddebug(x , y)  cerr << #x << " = " << x << "   " << #y << " = " << y << '\n'
#define ios std::ios::sync_with_stdio(false) , cin.tie(0)
using namespace std ;
typedef long long ll ;
typedef long double ld ;
typedef pair<int , int> pii ;
typedef pair<ll , ll> pll ;
typedef double db ;
const int mod = 998244353 ;
const int maxn = 2e5 + 10 ;
const int inf = 0x3f3f3f3f ;
const double eps = 1e-6 ; 
int n , a[maxn] ;
bool ok(ll x)
{
    ll res = 0 ;
    rep(i , 1 , n)  if(a[i] < x)  res += x - a[i] ;
    return res <= x ;
}
int main()
{
    ios ;
    int T ;
    int cas = 0 ;
    cin >> T ;
    while(T --)
    {
        cin >> n ;
        rep(i , 1 , n)  cin >> a[i] ;
        ll l = 0 , r = 2e9 ;
        ll ans = l ;
        while(l <= r)
        {
            ll mid = (l + r) / 2 ;
            if(ok(mid))  ans = mid , l = mid + 1 ;
            else  r = mid - 1 ;
        }
        cout << "Case #" << ++ cas << ": " << ans + 1 << '\n' ;
    }
    return 0 ;
}

J题

不好意思,我看到题就直接去魔改吉司机线段树了。区间取最大值,区间查询最大值。直接做就行了。

不过如果你对亮度排序后,直接区间覆盖就好了。。。裸的线段树就行了。

如果你像我一样只会莽的话会写的比较慢一些。区间覆盖就好写很多了。

#include<bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
#define sz(x)  (int)x.size()
#define cl(x)  x.clear()
#define all(x)  x.begin() , x.end()
#define rep(i , x , n)  for(int i = x ; i <= n ; i ++)
#define per(i , n , x)  for(int i = n ; i >= x ; i --)
#define mem0(x)  memset(x , 0 , sizeof(x))
#define mem_1(x)  memset(x , -1 , sizeof(x))
#define mem_inf(x)  memset(x , 0x3f , sizeof(x))
#define debug(x)  cerr << #x << " = " << x << '\n'
#define ddebug(x , y)  cerr << #x << " = " << x << "   " << #y << " = " << y << '\n'
#define ios std::ios::sync_with_stdio(false) , cin.tie(0)
using namespace std ;
typedef long long ll ;
typedef long double ld ;
typedef pair<int , int> pii ;
typedef pair<ll , ll> pll ;
typedef double db ;
const int mod = 998244353 ;
const int maxn = 1e5 + 10 ;
const int inf = 0x3f3f3f3f ;
const double eps = 1e-6 ; 
int n , m , a[maxn] ;
struct jls_seg
{
    int mn[maxn << 2] , se_mn[maxn << 2] ;
    int mx[maxn << 2] ;
    int ls(int x)
    {
        return x << 1 ;
    }
    int rs(int x)
    {
        return x << 1 | 1 ;
    }
    void push_up(int id)
    {
        mx[id] = max(mx[ls(id)] , mx[rs(id)]) ;
        mn[id] = min(mn[ls(id)] , mn[rs(id)]) ;
        se_mn[id] = min(se_mn[ls(id)] , se_mn[rs(id)]) ;
        if(mn[ls(id)] != mn[rs(id)])  se_mn[id] = min(se_mn[id] , max(mn[ls(id)] , mn[rs(id)])) ;
    }
    void dec_tag(int id , int v)
    {
        if(v <= mn[id])  return ; 
        mn[id] = v ;
        mx[id] = max(mx[id] , v) ;
    }
    void push_down(int id)
    {
        dec_tag(ls(id) , mn[id]) ;
        dec_tag(rs(id) , mn[id]) ;
    }
    void init()
    {
        rep(i , 1 , m << 2)  mx[i] = 0 , mn[i] = 0 , se_mn[i] = inf ;
    }
    void update(int id , int l , int r , int x , int y , int v)
    {
        //if(v <= mn[id])  return ;
        if(r < l || y < x || v <= mn[id])  return ;
        //ddebug(l , r) ;
        if(l == x  &&  r == y && v < se_mn[id])
        {
            //debug(222) ;
            dec_tag(id , v) ;
            return ;
        }
        push_down(id) ;
        int mid = (l + r) / 2 ;
        if(y <= mid) update(ls(id) , l , mid , x , y , v) ;
        else if(x > mid) update(rs(id) , mid + 1 , r , x , y , v) ;
        else update(ls(id) , l , mid , x , mid , v) , update(rs(id) , mid + 1 , r , mid + 1 , y , v) ;
        push_up(id) ;   
    }
    int query_max(int id , int l , int r , int x , int y)
    {
        // debug(mx[id]) ;
        if(l == x && r == y) return mx[id] ;
        push_down(id) ;
        int mid = (l + r) / 2 ;
        if(y <= mid) return query_max(ls(id) , l , mid , x , y) ;
        else if(x > mid) return query_max(rs(id) , mid + 1 , r , x , y) ;
        else return max(query_max(ls(id) , l , mid , x , mid) , query_max(rs(id) , mid + 1 , r , mid + 1 , y)) ;
    }
} seg ;
void solve(int cas)
{
    cin >> n >> m ;
    rep(i , 1 , m)  a[i] = 0 ;
    rep(i , 1 , n)
    {
        int t , x ;
        cin >> t >> x ;
        int tmp = min(t , m) ;
        a[tmp] = max(a[tmp] , x) ;
    }
    seg.init() ;
    rep(t , 1 , m)  for(int j = 1 ; j <= m ; j += 2 * t)  seg.update(1 , 1 , m , j , j + t - 1 , a[t]) ;
    cout << "Case #" << cas << ": " ;
    rep(i , 1 , m)  cout << seg.query_max(1 , 1 , m , i , i) << " \n"[i == m] ;
}
int main()
{
    ios ;
    int T ;
    cin >> T ;
    rep(i , 1 , T)  solve(i) ;
    return 0 ;
}

K题

奇数就拆成奇数和偶数,答案是1。

偶数凭借直感,要么分成2个数,要么分成3个数,打个表规律就全出来了,分成两个数周期是2,分成3个数周期是3,取个最小值就行了。

#include<bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
#define sz(x)  (int)x.size()
#define cl(x)  x.clear()
#define all(x)  x.begin() , x.end()
#define rep(i , x , n)  for(int i = x ; i <= n ; i ++)
#define per(i , n , x)  for(int i = n ; i >= x ; i --)
#define mem0(x)  memset(x , 0 , sizeof(x))
#define mem_1(x)  memset(x , -1 , sizeof(x))
#define mem_inf(x)  memset(x , 0x3f , sizeof(x))
#define debug(x)  cerr << #x << " = " << x << '\n'
#define ddebug(x , y)  cerr << #x << " = " << x << "   " << #y << " = " << y << '\n'
#define ios std::ios::sync_with_stdio(false) , cin.tie(0)
using namespace std ;
typedef long long ll ;
typedef long double ld ;
typedef pair<int , int> pii ;
typedef pair<ll , ll> pll ;
typedef double db ;
const int mod = 998244353 ;
const int maxn = 2e5 + 10 ;
const int inf = 0x3f3f3f3f ;
const double eps = 1e-6 ; 

int main()
{
    ios ;
    int T ;
    cin >> T ;
    rep(cas , 1 , T)
    {
        int x ;
        cin >> x ;
        if(x == 6)  cout << "Case #" << cas << ": " << -1 << '\n' ;
        else if(x % 2 == 1)  cout << "Case #" << cas << ": " << 1 << '\n' ;
        else
        {
            if(x % 6 == 0)  cout << "Case #" << cas << ": " << 2 << '\n' ;
            else if(x % 6 == 2)  
            {
                int ans = 4 ;
                if(abs(x - 14) % 18 != 0)  ans = 3 ;
                if(abs(x - 14) % 12 == 6)  ans = 2 ;
                cout << "Case #" << cas << ": " << ans << '\n' ;
            }
            else
            {
                int ans = 4 ;
                if(abs(x - 22) % 18 != 0)  ans = 3 ;
                if(abs(x - 22) % 12 == 6)  ans = 2 ;
                cout << "Case #" << cas << ": " << ans << '\n' ;
            }
        }
    }
    return 0 ;
}

L题

这位哥学的。

#include<bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
#define sz(x)  (int)x.size()
#define cl(x)  x.clear()
#define all(x)  x.begin() , x.end()
#define rep(i , x , n)  for(int i = x ; i <= n ; i ++)
#define per(i , n , x)  for(int i = n ; i >= x ; i --)
#define mem0(x)  memset(x , 0 , sizeof(x))
#define mem_1(x)  memset(x , -1 , sizeof(x))
#define mem_inf(x)  memset(x , 0x3f , sizeof(x))
#define debug(x)  cerr << #x << " = " << x << '\n'
#define ddebug(x , y)  cerr << #x << " = " << x << "   " << #y << " = " << y << '\n'
#define ios std::ios::sync_with_stdio(false) , cin.tie(0)
using namespace std ;
typedef long long ll ;
typedef long double ld ;
typedef pair<int , int> pii ;
typedef pair<ll , ll> pll ;
typedef double db ;
const int mod = 1e9 + 7 ;
const int maxn = 2e5 + 10 ;
const int inf = 0x3f3f3f3f ;
const double eps = 1e-6 ; 
struct Easymath
{
    ll qpow(ll a , ll b) //快速幂
    {
        if(b < 0)  return 0 ;
        ll ans = 1 ; 
        a %= mod ;
        while(b)
        {
            if(b & 1)  ans = (ans * a) % mod ;
            b >>= 1 , a = (a * a) % mod ;
        }
        return ans % mod ;
    }
    ll ksc_log(ll x , ll y , ll mod) //快速乘
    {
        x %= mod , y %= mod ;
        ll ans = 0;
        while(y)
        {
            if(y & 1) ans = (ans + x) % mod ; 
            y >>= 1 ;
            x = (x + x) % mod ;
        }
        return ans;
    }
    ll ksc_O1(ll x , ll y , ll mod) //快速乘
    {
        x %= mod , y %= mod ;
        ll z = (ld)x * y / mod ;
        ll ans = x * y - z * mod ;
        if(ans < 0)  ans += mod ;
        else if(ans >= mod)  ans -= mod ;
        return ans ;
    }
    int cnt = 0 ;
    bool vis[maxn] ;
    int prime[maxn] ;
    void get_prime(int up) //素数筛
    {
        memset(vis , 0 , sizeof(vis)) ;
        vis[1] = 1 ;
        for(int i = 2 ; i <= up ; i ++)
        {
            if(!vis[i]) 
            prime[++ cnt] = i ;
            for(int j = 1 ; j <= cnt && i * prime[j] <= up ; j ++)
            {
                vis[i * prime[j]] = 1 ;
                if(i % prime[j] == 0) break ;
            }
        }
    }
    //begin 判定大素数
    ll mul(ll a , ll b , ll mod)
    {
        ll ret = 0 ;
        while(b) 
        {
            if(b & 1)  ret = (ret + a) % mod ;
            a = (a + a) % mod ;
            b >>= 1 ;
        }
        return ret ;
    }
    ll pow(ll a , ll b , ll mod)
    {
        ll ret = 1 ;
        while(b) 
        {
            if(b & 1)  ret = mul(ret , a , mod) ;
            a = mul(a , a , mod) ;
            b >>= 1 ;
        }
        return ret ;
    }
    bool check(ll a , ll n)
    {
        ll x = n - 1 ;
        int t = 0 ;
        while((x & 1) == 0) 
        {
            x >>= 1 ;
            t ++ ;
        }
        x = pow(a , x , n) ;
        ll y ;
        rep(i , 1 , t)
        {
            y = mul(x , x , n) ;
            if(y == 1 && x != 1 && x != n - 1)  return 1 ;
            x = y ;
        }
        if(y != 1) return 1 ;
        return 0 ;
    }
    bool Miller_Rabin(ll n) 
    {
        if(n == 2)  return 1 ;
        if(n == 1 || !(n & 1))  return 0 ;
        const int arr[12] = {2,3,5,7,11,13,17,19,23,29,31,37} ;
        rep(i , 0 , 11) 
        {
            if(arr[i] >= n) break ;
            if(check(arr[i] , n)) return 0 ;
        }
        return 1 ;
    }
    //end 判定大素数
    ll get_inv(ll x) //逆元
    {
       return qpow(x , mod - 2) % mod ;
    }
    ll inv1[maxn] ;  //乘法逆元
    void init1(int up)
    {
       inv1[1] = 1 ;
       for(int i = 2 ; i <= up ; i ++)
         inv1[i] = (ll)(mod - mod / i) * inv1[int(mod % (ll)i)] % mod ;
    }
    ll fac[maxn] ;
    ll inv[maxn] ; //阶乘逆元
    void init(int up) 
    {
       fac[0] = fac[1] = inv[0] = inv[1] = 1 ;
       for(int i = 2 ; i <= up ; i ++)
       {
         fac[i] = fac[i - 1] * i % mod ;
         inv[i] = -inv[mod % i] * (mod / i) % mod ;
         while(inv[i] < 0) inv[i] += mod ;
       }
       for(int i = 2 ; i <= up ; i ++)  
         inv[i] = inv[i] * inv[i - 1] % mod ;
    }
    ll C(int n , int m)
    {
        return fac[n] * inv[m] % mod * inv[n - m] % mod ;
    }
} em ;
int n ;
struct node
{
    int a , x ;
    bool operator < (const node &s) const
    {
        return a < s.a ;
    }
} b[maxn] ;
bool can(int i , int j , ll &res)
{
    int now = b[i].a ;
    while(now < b[j].a && res >= 2)  res /= 2 , now ++ ;
    if(now == b[j].a)
    {
        res += b[j].x ;
        return 1 ;
    }
    else  return 0 ;
}
ll cal(int i , int j)
{
    ll sum = 0 ;
    per(k , j , i)
    {
        if(k == j)  sum = sum * 2 % mod + b[k].x ;
        else  sum = sum * em.qpow(2 , b[k + 1].a - b[k].a) % mod + b[k].x ;
        sum %= mod ;
    }
    sum = (sum + 1) % mod ;
    return sum ;
}
int main()
{
    ios ;
    int T ;
    cin >> T ;
    rep(cas , 1 , T)
    {
        cin >> n ;
        rep(i , 1 , n)  cin >> b[i].a >> b[i].x ;
        sort(b + 1 , b + n + 1) ;
        ll ans = 1 ;
        rep(i , 1 , n)
        {
            int j = i ;
            ll res = b[i].x ;
            while(j + 1 <= n && can(j , j + 1 , res))  j ++ ;
            ans *= cal(i , j) ;
            ans %= mod ;
            i = j ;
        }
        cout << "Case #" << cas << ": " << ans << '\n' ;
    }
    return 0 ;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值