2015年ACM上海大都会邀请赛总结

更新记录

H题成功拿到HDU statistic rank1!(我TM是有多闲。。)
已经完成赛后AK!可喜可贺!虽然这个AK的周期略长。。都是我太弱。。
AK!!!

比赛经历

非常神奇的一场比赛,两百多个队在一个体育馆(羽毛球馆)内比赛,两桌距离不超过半米。自己的桌牌在别人的电脑后面,直接导致我们对面的队一开始直接坐了我们的位置。正式比赛还拿了我们的题。。。


热身赛

首先,题目直接在比赛前放在了桌上。没有信封!
tomriddly直接抄起了题看了一眼,发现是题,就扣下了!但是这一瞬间就读完了A题题意!然后!然后!在调试Eclipse的时候!写完了A题。
结果。
结果。
并没有拿到runid 1
交上去已经runid 14了
然后,
就没有然后了。

A题 求2的n次方,要用高精度。
B题 给一个n*m的考场,有一些位置不能坐人,每个人能看到左右以及左前方右前方的人的试卷。(类似于国际象棋棋盘上放最多的兵),二分图即可。
C题 有n道题,给出每道题通过的人数,问过了C道题及以上的人最多有多少。
这题我们当时没有想到正解。其实要想每个人都过题多,只要尽量使得每人过题数尽量平均即可。这时候可以想到二分总人数,来验证答案。再更新一个最大值即可。


正赛

jiefangxuanyan一开始就瞄上了J题,然后以迅雷不及掩耳之势算出了公式,成功1Y拿下一血和一个很胖的一血气球(志愿者发气球的时候还砸到了对面的同学的脑袋,简直了)。然后看到榜上E过了好多,于是tomriddly就写了E,然后1Y。然后jiefangxuanyan刷刷刷敲了B题,是个模拟。然后我们觉得D应该是一个线段树,在解决了longlong*longlong的问题之后(汇编乘法挂,详情请问本人),tomriddly一顿敲,直到觉得自己写不出像样的lazy标记。。
这时znl1087jiefangxuanyan发现F是个脑筋急转弯。。。。
然后把tomriddly赶下键盘,jiefangxuanyan成功使用java获得1Y
然后是一个漫长的空键盘阶段,将近一个小时。。当时场上一部分人过了G题,一部分人过了A,有几个人过了D。然后开始每个人轮流想这几道题。。在一个小时之后,tomriddly想出了G的做法。虽然znl1087jiefangxuanyan都没听明白,但是本着不让键盘空着(虽然TMD已经空了一个小时)的原则,让他上去写了。好久之后(其实就是他写了好久好久,调了好久好久,期间还上了一个大号),写完了,但是WA了。这个时候jiefangxuanyan成功推出A题公式。。然后上键盘微调1Y。然后tomriddly惊奇的发现自己的程序居然写的是int dfs(xxxxx) 说好的long long呢!
然后过了。此时大概还有一个半小时。然后tomriddly说我们一定还要再过一题!我们俩很认同的点了点头。然后三个人同时想D。
然后jiefangxuanyan感觉这个巨大的MOD有一些奇怪,应该有一些奇怪的性质。。znl1087提出,可能会出现循环。然后用python打了个表。居然真TM有循环,并且经过测试,30次以内必出!
于是,去掉lazy,特别简单的线段树,1Y(当然是开了某个挂的)
然后已经A了7题,还剩48分钟。估计了一下排名,大概金牌是稳了。。于是tomriddly劝告我们,再做一题就赚了!不然也不亏(废话)
于是大家一起找I题的规律。。。。
然而并没有找出来。。。。
然后比赛就结束了。。。。。


午饭

赛前我们三个人讨论了一下当天的午饭会发啥,tomriddly预测应该会比省赛四省赛的时候工大发的好。znl1087根据赛场布置风格推测,估计连马可波罗肠都没有。。。结果。。。结果。。。
奶茶加面包。。。。
没了。。
没了。。


正赛题解


A Article

题意

DRD经常使用一个文本处理软件,这个软件每输入一个字符就有一定的概率(p)崩溃,并且丢失上次保存之后的所有数据。执行一次保存需要x字符的代价(但是不会崩溃)问在最优策略下,输入字符的期望是多少

思路

首先考虑一次性完成i个字符输入的期望e[i]。发现是一个近似的等比数列。根据推出来的公式,每次保存之间的间隔尽量平均是最优解。预处理出e[i],然后枚举保存的次数,O(1)计算出期望,取期望最小的值为答案。

证明

如图:
A题证明

AC代码

HDU5236,注意这题没有special judge,不写%.6f输出会WA

/* written by jiefangxuanyan */
#include <cstdio>
#include <cmath>
#include <cfloat>
#include <algorithm>
const int N=110000;
double t[N];
int main(){
    int cn;
    scanf("%d",&cn);
    for(int ci=1;ci<=cn;ci++){
        int n;
        double fail;
        int save;
        scanf("%d%lf%d",&n,&fail,&save);
        t[0]=0;
        for(int i=1;i<=n;i++){
            t[i]=(t[i-1]+1)/(1-fail);
        }
        t[n+1]=0;
        double s=DBL_MAX;
        for(int k=1;k<=n;k++){
            int left=n%k;
            s=std::min(t[n/k+1]*left+t[n/k]*(k-left)+save*k,s);
        }
        printf("Case #%d: %.6f\n",ci,s);
    }
    return 0;
}

B Base64

题意

base64编码,对一个字符串进行n次base64编码,输出答案。

思路

同上。。

AC代码

hdu5237

/* written by tomriddly */
#include <bits/stdc++.h>
using namespace std;
string Encode(const char* Data,int DataByte)
{
    //编码表
    const char EncodeTable[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    //返回值
    string strEncode;
    char Tmp[4]= {
  0};
    int LineLength=0;
    for(int i=0; i<(int)(DataByte / 3); i++)
    {
        Tmp[1] = *Data++;
        Tmp[2] = *Data++;
        Tmp[3] = *Data++;
        strEncode+= EncodeTable[Tmp[1] >> 2];
        strEncode+= EncodeTable[((Tmp[1] << 4) | (Tmp[2] >> 4)) & 0x3F];
        strEncode+= EncodeTable[((Tmp[2] << 2) | (Tmp[3] >> 6)) & 0x3F];
        strEncode+= EncodeTable[Tmp[3] & 0x3F];
    }
    //对剩余数据进行编码
    int Mod=DataByte % 3;
    if(Mod==1)
    {
        Tmp[1] = *Data++;
        strEncode+= EncodeTable[(Tmp[1] & 0xFC) >> 2];
        strEncode+= EncodeTable[((Tmp[1] & 0x03) << 4)];
        strEncode+= "==";
    }
    else if(Mod==2)
    {
        Tmp[1] = *Data++;
        Tmp[2] = *Data++;
        strEncode+= EncodeTable[(Tmp[1] & 0xFC) >> 2];
        strEncode+= EncodeTable[((Tmp[1] & 0x03) << 4) | ((Tmp[2] & 0xF0) >> 4)];
        strEncode+= EncodeTable[((Tmp[2] & 0x0F) << 2)];
        strEncode+= "=";
    }

    return strEncode;
}
int n;
string a;
int main()
{
    int fuck;
    scanf("%d", &fuck);
    for (int cas = 1; cas <= fuck; cas++)
    {
        cin >> n >> a;
        for (int i = 1; i <= n; i++)
            a = Encode(a.c_str(), a.length());
        cout << "Case #" << cas << ": " << a << endl;
    }
    return 0;
}

C Calculator

题意

给出一个计算的序列,包含{+,*,^}三种运算。给出两种操作,1是给出初始值,求按照序列计算的答案,2是修改序列中某个位置的数和运算符。

思路

比赛的时候没想出来,比完赛想出来了。首先题目中,用来MOD的值是一个比较小的数,所以大概思路是把一个区间的运算维护成一个a[mod]大小的映射。但是mod = 29393貌似又太大,于是想到把29393 = 7 * 13 * 17 * 19,然后分别维护这四个因数的线段树,然后利用中国剩余定理算出最后答案。维护区间用线段树去实现,可以把映射单独写成一个数据结构,然后开这个数据结构的线段树。
单点修改,并且只查询根节点,线段树操作非常简单。
jiefangxuanyan写代码的时候碰到一些细节问题,不过比赛的时候队友在旁边看,肯定不会出现这些问题的。

AC代码

HDU5238

/* written by jiefangxuanyan */
#include <cstdio>
#include <cstring>
#include <algorithm>
template<int base>
class Mapping{
    int tgt[base];
public:
    int &operator[](int pos){
        return tgt[pos];
    }
    void clear(){
        for(int i=0;i<base;i++){
            tgt[i]=i;
        }
    }
    void setAdd(int a){
        for(int i=0;i<base;i++){
            tgt[i]=(i+a)%base;
        }
    }
    void setMul(int a){
        for(int i=0;i<base;i++){
            tgt[i]=(i*a)%base;
        }
    }
    void setPow(
  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 25
    评论
评论 25
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值