2017ACM EC Final 补题题解

M World Cup

傻逼签到不多说
代码

#include
#include
#include 
using namespace std;
const int maxn=100005;
const int base=131;
typedef long long ll;
#define pi acos(-1)
#define INF 0x3f3f3f3f
#define mod 998244353
const int inf=1<<30;
ll p[10];

ll slove(int id)
{
     
    if(id >= 1 && id < 49)
        return p[1];
    if(id >= 49 && id < 57)
        return p[2];
    if(id >=57 && id < 61)
        return p[3];   
    if(id >=61 && id < 63)
        return p[4];
    return p[5];  
}
int main()
{
     
    int t,n;
    cin>>t;
    for(int j = 1; j <= t ;j++){
     
        for(int i = 1; i <= 5; i++)
            scanf("%lld",&p[i]);
        scanf("%d",&n);
        int id;
        ll ans = 0;
        for(int i =1;i <= n;i++){
     
            scanf("%d",&id);
            ans += slove(id);
        }
        ans *= 10000;
        printf("Case #%d: %lld\n",j,ans);
    }
    return 0;
}

A Chat Group

数学题
看一下n的数据范围,显然直接暴力不可能,看一下k的数据1e5,可以想到往k上面转化。
经典二项式的性质Cn0+Cn1+Cn2+……cnn=2^n,直接把加法转化为减法。注意由于算组合数有分母,需要用到逆元。
然后取余这个东西真的恶心,建议有结果的地方就取余,少了一个取余被卡了一小时还换了一种写法。
代码一(提前处理阶乘和全排列)

#include
#include
#include 
using namespace std;
const int maxn=100005;
const int base=131;
typedef long long ll;
#define pi acos(-1)
#define INF 0x3f3f3f3f
#define mod 1000000007
const int inf=1<<30;
ll A[maxn];
ll J[maxn];
ll ksm(ll a,ll b,ll m)
{
     
    ll ans = 1;
    while(b){
     
        if(b & 1) ans = (ans*a) % m ;
        a = (a * a) % m;
        b >>= 1;
    }
    return ans;
}
 
void amn(ll m,ll n){
     
    A[0] = 1;
    for(ll i = 1,j = m;i<= n;i++){
     
        A[i] = A[i-1] * j;
        A[i] %= mod;
        j--; 
    }
}
 
void jiechen(ll k)
{
     
    J[0] = 1;
    for(int i  = 1 ; i <= k;i++ ){
     
        J[i] = (J[i-1] * i) % mod;
    }
}
 
ll cmn(ll m ,ll n)
{
     
    return (A[n] * ksm(J[n],mod-2,mod)) %mod;
}
 
int main()
{
     
    int t,n,k;
    cin>>t;
    jiechen(100000);
    for(int i = 1; i <= t; i++){
     
        cin>>n>>k;
        if( k > n){
     
            printf("Case #%d: 0\n",i);
            continue;
        }
        ll ans = ksm(2,n,mod);
        ll jishu = 0;
        amn(n,k);
        for(ll j = k-1 ; j >= 0; j--){
     
            jishu += cmn(n,j);
            jishu %= mod;
        }
        ans = (ans - jishu + mod) % mod;
        printf("Case #%d: %lld\n",i,ans);
    }
    return 0;
}

代码二 递推处理

#include
#include
#include 
using namespace std;
const int maxn=100005;
const int base=131;
typedef long long ll;
#define pi acos(-1)
#define INF 0x3f3f3f3f
#define mod 1000000007
const int inf=1<<30;
ll A[maxn];
ll J[maxn];
ll ksm(ll a,ll b,ll m)
{
     
    ll ans = 1;
    while(b){
     
        if(b & 1) ans = (ans*a) % m ;
        a = (a * a) % m;
        b >>= 1;
    }
    return ans;
}
 
int main()
{
     
    int t,n,k;
    cin>>t;
    for(int i = 1; i <= t; i++){
     
        cin>>n>>k;
        if( k > n){
     
            printf("Case #%d: 0\n",i);
            continue;
        }
        ll ans = ksm(2,n,mod);
        ll jishu = 1;
        ll tmp = 1;
        for(ll j = 1,kk = n ; j <= k-1; j++){
     
            tmp = ((tmp * kk) % mod * ksm(j,mod-2,mod)) %mod;
            kk--;
            jishu += tmp;
            jishu %= mod;
        }
        ans = (ans - jishu + mod) % mod;
        printf("Case #%d: %lld\n",i,ans);
    }
    return 0;
}

KDowngrade

阅读理解题
可能是我英语不好吧,反正看了题解才知道题意。虽然它叫降级但是题意好像和降级并没有什么关系。
拿样例举例此时位于A-B(3-2),这一天羊神缺席,B舍弃,A转化为经验值3点,从零开始升级就是2-1,继续第二天,1舍弃,2转化为经验值2点,从零开始升级就是1-2。
题意知道了就是纯模拟了。
代码:(二分查找)

#include
#include
#include 
using namespace std;
const int maxn=100005;
const int base=131;
typedef long long ll;
#define pi acos(-1)
#define INF 0x3f3f3f3f
#define mod 1000000007
const int inf=1<<30;
ll l[maxn];
ll up[maxn];
 
ll find(ll x)
{
     
    ll l = 1;
    ll r = x;
    while(l <= r){
     
        ll m = (l + r) / 2;
        if(up[m] < x && up[m+1] >= x)
            return m;
        else if(x <= up[m])
            r = m-1;
        else
            l = m+1;
    }
    return 0;
}
 
int main()
{
     
    int t,a,b,n;
    cin>>t;
    for(int c = 1; c <= t ; c++ ){
     
        memset(up,0,sizeof(up));
        cin>>a>>b>>n;
        for(int i = 1; i <= a; i++){
     
            scanf("%lld",&l[i]);
            up[i] = up[i-1] + l[i];
        }
        ll x,y,lx;
        x = a;
        y = b;
        while(n--){
     
            if(x == lx)
                break;
            lx = x;
            x = find(x) + 1;
            y = lx - up[x-1];
        }
         printf("Case #%d: %lld-%lld\n",c,x,y); 
    }
    return 0;
}

普通:

#include
#include
#include 
using namespace std;
const int maxn=100005;
const int base=131;
typedef long long ll;
#define pi acos(-1)
#define INF 0x3f3f3f3f
#define mod 1000000007
const int inf=1<<30;
ll l[maxn];

int main()
{
     
    int t,a,b,n;
    cin>>t;
    for(int c = 1; c <= t ; c++ ){
     
        cin>>a>>b>>n;
        for(int i = 1; i <= a; i++)
            scanf("%lld",&l[i]);
        ll x,y,lx;
        x = a;
        y = b;
        while(n--){
     
            if(x == lx)
                break;
            lx = x;
            y = x;
            x = 1;
            for(int i = 1; i <= x;i++){
     
                if(y > l[i]){
     
                    y -= l[i];
                    x++;
                }
                else
                    break;
            }
            if(x == 1 && y == 1)
                break;
        }
        printf("Case #%d: %lld-%lld\n",c,x,y); 
    }
    return 0;
}

CTraffic Light

又是一个阅读理解,最糟糕的情况下最短时间就是等最长的红灯,其他都是绿灯。

#include
#include
#include 
using namespace std;
const int maxn=100005;
const int base=131;
typedef long long ll;
#define pi acos(-1)
#define INF 0x3f3f3f3f
#define mod 1000000007
const int inf=1<<30;
ll s[maxn];
ll a[maxn],b[maxn];
 
int main()
{
     
    int t,n;
    cin>>t;
    for(int c =1 ;c <= t ;c++){
     
        cin>>n;
        double ans = 0.0;
        for(int i = 1;i <= n+1; i++){
     
            scanf("%lld",&s[i]);
            ans += s[i];
        }
        for(int i = 1;i <= n; i++ )
            scanf("%lld %lld",&a[i],&b[i]);
        sort(b+1, b+1+n);
        ans += b[n];
        printf("Case #%d: %.8lf\n",c,ans); 
    }
    return 0;
}

B. Scapegoat

题意:每个人都对应一个麻烦,n个人可以对应同一个麻烦,找最小方差。

思路:一个贪心的思维,平均值一定,那么先把所有的麻烦分出去,这时候有一个方差,然后加人,每个麻烦下面都可以加,然后计算方差的变化,每次往下降最多的那个麻烦下加人。

不会写重载比较操作符函数,见下图
2017ACM EC Final 补题题解_第1张图片
代码


 - #include<bits/stdc++.h>
   #include
   #include  using namespace std; const int maxn=200005; const int base=131; typedef long long ll;
   #define pi acos(-1)
   #define INF 0x3f3f3f3f
   #define mod 998244353 const int inf=1<<30; double a[maxn]; double avg,sum;
   
   struct node {
     
       double num,cnt;
       double val;
   
       bool operator < (const node& b) const {
     
           return val < b.val;
       } };
   
   double cal(node x) {
     
       return  x.cnt * (x.num / x.cnt - avg) * (x.num / x.cnt - avg) - (x.cnt + 1) * (x.num / (x.cnt + 1) - avg) * (x.num / (x.cnt + 1) -
   avg);//增加一个后方差的减小量  }
   
   int main() {
     
       int t,n,m;
       cin>>t;
       for (int c = 1; c <= t; c++)
       {
     
           double ans = 0.0;
           sum = 0.0;
           cin>>n>>m;
           for(int i = 1 ;i <= n; i++){
     
               scanf("%lf",&a[i]);
               sum += a[i];
           }
           avg = sum / m;
           priority_queue<node> q;
           for(int i = 1 ;i <= n; i++){
     
               node now;
               now.num = a[i];
               now.cnt = 1;
               now.val = cal(now);
               q.push(now);
           } 
           for(int i = 1 ;i <= m - n; i++){
     
               node now = q.top();
               q.pop();
               now.cnt++;
               now.val = cal(now);
               q.push(now);
           }
           while(!q.empty()){
     
               node now = q.top();
               q.pop();
               ans += now.cnt * (now.num / now.cnt - avg) * (now.num / now.cnt - avg);
           }
           //cout<
           printf("Case #%d: %.12lf\n",c,ans/m);
       }
       
       return 0; }

以上是铜牌题

你可能感兴趣的:(ACM)