2021牛客国庆集训派对day5 题解-A,B,F,G,J


J-plan

有n个学生要去旅行。酒店有两种类型的房间:双人房和三人间。双人房的价格是p2,三人房的价格是p3
现在你需要计算这些学生的最低总成本。
求得最小公倍数为6
p32 >= p23 时(双人间更实惠)
两种情况:
一:当n%2 == 0 即刚好双人间可住满 , 输出 n/2 p2
二:当n%2 == 1 可分为两种方案,剩一个人住双人间和剩三个人住三人间 去最小值:
min( n/2
p2+p2 , (n/2-1)p2+p3 )
当 p3
2 < p23 时
三种情况:
if( n%3 == 0 ) cout << n/3
p3 << endl ;三人间住满
else if( n%3 == 1 ) cout << min( n/3p3+p2 , (n/3-1)p3+2p2 ) << endl ;余下一个人,选择双人间或者余下四人选两个双人间
else cout << min( n/3
p3+p2 , n/3*p3+p3 ) << endl ;余下两个人,选择双人间或者选三人间
AC代码:

void solve() 
{
    int n , p2 , p3 ;
    cin >> n >> p2 >> p3 ;
    if( p3*2 >= p2*3  ){
        if( n%2 == 0 ) cout << n/2 *p2 << endl ;
        else cout << min( n/2*p2+p2 , (n/2-1)*p2+p3 ) << endl ;
    }
    else {
        if( n%3 == 0 ) cout << n/3*p3 << endl ;
        else if( n%3 == 1 ) cout << min( n/3*p3+p2 , (n/3-1)*p3+2*p2 ) << endl ;
        else cout << min( n/3*p3+p2 , n/3*p3+p3 ) << endl ;
    }
    return ;
}


G-Max

给出两个正整数c,n。你需要找到一对满足1<=a,b<=n的整数(a,b),a和b的最大公除法是c。你需要最大化a和b的乘积
当c > n 时 无解
当 n==c 时 输出 cc
当c < n 时 输出 c
c*(n/c)*(n/c-1)
★★
A-gpa

经典二分 对于答案 res,
∑ i = 1 n s [ i ] ∗ c [ i ] ∑ i = 1 n s [ i ] \frac{\sum_{i=1}^ns[i]*c[i]}{\sum_{i=1}^ns[i]} i=1ns[i]i=1ns[i]c[i] > res
<=> ∑ i = 1 n s [ i ] ∗ c [ i ] \sum_{i=1}^ns[i]*c[i] i=1ns[i]c[i] > ∑ i = 1 n ( s [ i ] ∗ r e s ) \sum_{i=1}^n(s[i]*res) i=1n(s[i]res)
<=> ∑ i = 1 n s [ i ] ∗ ( c [ i ] − r e s ) \sum_{i=1}^ns[i]*(c[i]-res) i=1ns[i](c[i]res) > 0
sort一遍减去最小的k个即可
AC代码:

int n , k ;
double s[N] ;
double c[N] ;
double w[N] ;
bool cmp( double x , double y )
{
    return x > y ;
}
int check( double x )
{
    double ans = 0 ;
    for( int i = 1 ; i <= n ; i ++ ){
        w[i] = s[i]*( c[i] - x ) ; 
    }
    sort( w+1 , w+n+1 , cmp ) ;
    for( int i = 1 ; i <= n-k ; i ++ ){
        ans += w[i] ;
    }
    if( ans >= 0 ) return 1 ;
    return 0 ;
}
void solve() 
{
    cin >> n >> k ;
    for( int i = 1 ; i <= n ; i ++ ){
        cin >> s[i] ;
    }
    for( int i = 1 ; i <= n ; i ++ ){
        cin >> c[i] ;
    }
    double l = 0 ;
    double r = 1e3 ;
    while( r-l > 0.000001 ){
        double mid = ( l+r ) / 2.0 ;
        if( check( mid ) ) l = mid ;
        else r = mid ; 
    }
    cout << fixed << setprecision(10) << l << endl ;
    return ;
}

★★★★
B-div

题意:求 x ∈ \in { n 2 + 1 n^2+1 n2+1 , n 2 + 2 n n^2+2n n2+2n } 满足 x 是 n 4 n^4 n4 的因子
规律推算
∵ \because x ∈ \in { n 2 + 1 n^2+1 n2+1 , n 2 + 2 n n^2+2n n2+2n } 即 n 2 + a n^2+a n2+a( 1 <= a <= 2n )是 n 4 n^4 n4 的因子
n 4 n^4 n4 - ( n 2 + a n^2+a n2+a)( n 2 − a n^2-a n2a) = a 2 a^2 a2
∴ \therefore n 2 + a n^2+a n2+a a 2 a^2 a2 的 因子
即 ( n 2 + a n^2+a n2+a)*m = a 2 a^2 a2
又 a <= 2n 故可得 m < 4 ,即 m = 1 ,2 ,3 ;
暴力枚举推算得到方程有两个
1: n 2 n_2 n2 = 6 n 1 6n_1 6n1- n 0 n_0 n0( n 0 n_0 n0=0 , n 1 n_1 n1=2)
2: n 2 n_2 n2 = 14 n 1 14n_1 14n1- n 0 n_0 n0( n 0 n_0 n0=0 , n 1 n_1 n1=6)
AC代码(python):

m = int(input())
x = 0
y = 2
while x<m:
    t = 6*y-x
    x = y
    y = t

ans = x
x = 0
y = 6

while x<m:
    t = 14*y-x
    x = y
    y = t

ans = min(ans, x)
print(ans)

★★★★
F-take

Kanade有n个盒子,第i个盒子有**p[i]概率有d[i]**大小的钻石。
起初,卡纳德有一颗0号的钻石。她将从1号到n号打开盒子。当她打开一个盒子时,如果盒子里有一颗钻石,而且它比她的钻石大,她会用她的钻石替换它。
现在需要计算预期的替换数量。
您只需要输出%998244353。
数学期望+树状数组
E(a+b+c+d…) = E(a)+E(b)+E©+…
枚举每个盒子的期望即可,因为盒子只有打开与不打开两种情况即0和1
sort钻石大小,从大到小排列,保证每次开第i个宝箱时,前面宝箱一定不打开
故推算公式为
∏ j = 1 i − 1 ( 100 − p [ j ] ) ∗ p [ i ] \prod_{j=1}^{i-1}( 100-p[j] )*p[i] j=1i1(100p[j])p[i] , i ∈ ( 1 , n ) i\in(1,n) i(1,n)
AC代码:

int QuickPow( int x , int pow )
{
    int res = 1 ;
    x %= Max ;
    // x %= mod ;
    while( pow ){
        if( pow & 1 ) res = ( res * x ) % Max  ;
        // if( pow & 1 ) res = ( res * x ) % mod  ;
        // if( pow & 1 ) res = res * x ;
        x = ( x * x ) % Max ;
        // x = ( x * x ) % mod ;
        // x = x*x ;
        pow >>= 1 ;
    }
    return res % Max ;
    // return res ;
    // return res % mod ;
}

int gcd( int a , int b )
{
    if(!b) return a ;
    return gcd( b , a%b ) ;
}
// 解决方案代码区--------------------------------------------------
const int N = 1e5+7 ;
const int M = 2e6+7 ;
struct node
{
    int w ;
    int p ;
    int id ;
    /* data */
};
node a[N] ;
int b[N] ;
int n ;
int lowbit( int x )
{
    return x & (-x) ;
}
bool cmp( node x , node y )
{
    if( x.w == y.w ) return x.id < y.id ;
    return x.w > y.w ;
}
int mul( int x )
{
    int ans = 1 ;
    while( x ){
        ans = ( ans*b[x] )%Max ;
        x -= lowbit(x) ;
    }
    return ans ;
}
void add( int x , int p )
{
    while( x <= n ){
        b[x] = ( b[x]*p )%Max ;
        x += lowbit( x ) ;
    }
}
void solve() 
{
    cin >> n ;
    for( int i = 1 ; i < N ; i ++ ) b[i] = 1 ;
    for( int i = 1 ; i <= n ; i ++ ){
        cin >> a[i].p >> a[i].w ;
        a[i].id = i ;
        // cout << b[i] << endl ;
    }
    sort( a+1 , a+n+1 , cmp ) ;
    int res = 0 ;
    for( int i = 1 ; i <= n ; i ++ ){
        res = ( res + 1ll*mul( a[i].id )%Max*( a[i].p%Max*( QuickPow( 100 , Max-2 )%Max )%Max)%Max )%Max ;
        // cout <<res << endl ;
        add( a[i].id , QuickPow( 100 , Max-2 )%Max*(100-a[i].p)%Max ) ;
    }
    cout << res << endl ;
    
    return ;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值