2020年第十四届山东大学程序设计竞赛

两个一血,舒服
在这里插入图片描述
----------------------------------------------------
A
在这里插入图片描述
在这里插入图片描述
模拟题,给出n个固定位置的值,然后给出目标位置值,每个固定位置只能向前走,求最小消耗
很简单,就是累和每个数与他左边最近的固定数的距离
我看数据范围不大,直接暴力打表了。。

int n;
string str[maxn];
string cup[96]={
"A1","A1#","B1","C1","C1#","D1","D1#","E1","F1","F1#","G1","G1#",
"A2","A2#","B2","C2","C2#","D2","D2#","E2","F2","F2#","G2","G2#",
"A3","A3#","B3","C3","C3#","D3","D3#","E3","F3","F3#","G3","G3#"
,"A4","A4#","B4","C4","C4#","D4","D4#","E4","F4","F4#","G4","G4#"
,"A5","A5#","B5","C5","C5#","D5","D5#","E5","F5","F5#","G5","G5#"
,"A6","A6#","B6","C6","C6#","D6","D6#","E6","F6","F6#","G6","G6#"
,"A7","A7#","B7","C7","C7#","D7","D7#","E7","F7","F7#","G7","G7#"
,"A8","A8#","B1","C8","C8#","D8","D8#","E8","F8","F8#","G8","G8#"};
bool judge(string str){
    if(str=="F1#"||str=="F2#"||str=="F3#"||str=="F4#"||str=="F5#"){
        return true;
    }else{
        return false;
    }
}
int seek(string str){
    int ed,st;
    rep(i,0,95){
        if(cup[i]==str){
            ed=i;
           // de(ed)
            per(j,i,0){
                if(judge(cup[j])){
                    return i-j;
                }
            }
        }
    }
}
int check(string str){
    rep(i,0,95){
        if(cup[i]==str){
            return i-1;
        }
    }
}
string change(string str){
    int sz=str.size();
    if(str[sz-1]=='b'){
        int num=str[1]-'A'+1;
        char ch=str[0];
        string c;
        c+=str[0];
        c+=str[1];
        int pos=check(c);
        c=cup[pos];
        return c;
    }else{
        return str;
    }
}
void solve(){
    int ans = 0;
    cin>>n;
    rep(i,1,n){
        cin>>str[i];
        str[i]=change(str[i]);
        //de(str[i])
        int dis=seek(str[i]);
        ans+=dis;
    }
    printf("%d\n",ans);
}

C
在这里插入图片描述
签到题,给出分裂方式,找出最初的形式
分裂方式很清楚了,所以我们只需要开两个 s t r i n g string 代表上下,奇数加上面,偶数加下面,然后依次输出就好了

void solve(){
    string str;
    cin>>str;
    int sz = str.size();
    string a="",b="";
    rep(i,0,sz-1){
        if(i%2==0){
            a+=str[i];
        }else{
            b+=str[i];
        }
    }
    cout<<a<<b<<endl;
}

D
在这里插入图片描述
第一眼,哇…数论题,溜了溜了
后来看过了好多人…心想怎么这么多数学选手啊…就会去看了看
然后就发现了精度问题…下面是指数函数,指数爆炸…精度大于 1 e 9 1e-9 就可以了,那就很简单了,很明显这个式子的值最后的变化范围很小很小,所以超过一定范围后保留 1 e 9 1e-9 ,就相当于i相同的数了,我没算具体大概有多大会趋于一致,直接打了个 1 e 6 1e6 的表,交了
对于大于1e6的数,答案在保留9位小数时肯定会等于1e6的

double ans[maxn];
double arr[maxn];
void solve(){
    int n =read();
    n=min(n,1000000);
    printf("%.10f\n",ans[n]);
}
int main(){
    arr[1]=1.0/2;
    arr[2]=1.0/4;
    ans[0]=0;
    for(int i=3;i<=1e6;i++){
        arr[i]=arr[i-2]*1.0/4+arr[i-1]*1.0/2;
    }
    for(int i=1;i<=1e6;i++){
        ans[i]=ans[i-1]+arr[i];
    }
    int test = 1;
    //test = read();
    //cin>>test;
    while(test--){
        solve();
    }
    #ifdef _LOCALE_DEBUG_PAUSE  
        system("pause");
    #endif //_LOCALE_DEBUGE_PAUSE
    return 0;
}

F
在这里插入图片描述
这个题我吐了,从wa到T到mle…
wa的原因是憨批了…错误思路就不说了
最小数目 很明显就是1,输出他自己
最大数目
要求 | ,或运算后结果为这个数,那么根据或运算的特点,一真即真,
那么方案数就应该从二进制角度下手,找出目的数在二进制下哪些位数为0,那么组成方案的数就不能含有这个位置为1的数
题目说数目不会大于1e6,算一下1e6二进制下有20位,瞎暴力差不多
先存下目标数二进制的表示,然后枚举二进制,找出所有或运算后不会破坏的数,放入set就可以了,,然后T了
正解应该是 :
找出这个数二进制下的位数 n u m num ,然后先特判放入数组一个0,之后,我们从低位到高位枚举这个数二进制的表示,如果为1,那么我们就选这个数对应的2的幂,加上前面所有比它小的数,并放入数组就可以了

int y;
int ans[maxn];
void solve(){
    y = read();
    puts("1");
    printf("%d\n",y);
    if(y==0){
        printf("1\n0\n");
        return ;
    }
    int tmp = y;
    int base = 1;
    int cnt = 0;
    int len = 0;
    ans[++len]=0;
    while(tmp){
        base = (1<<cnt);
        if(tmp&1){
            int ed=len;
           rep(i,1,len){
               ans[++ed]=base+ans[i];
           }
           len=ed;
        }
        cnt++;
        tmp>>=1;
    }
    printf("%d\n",len);
    rep(i,1,len){
        printf("%d\n",ans[i]);
    }
}

L
在这里插入图片描述
看题目有意思就点了,然后开到一个签到题,笑死我了
抢了个一血
这个没啥好说的,就是一个取模

void solve(){
    int x = read(),n = read();
    int ans = (x+n-1)%7+1;
    printf("%d\n",ans);
}

M
在这里插入图片描述
最长上升子序列板子题
我拿一血啦
区别在于输出路径且要求字典序最大,关于记录路径问题
我们只需要多加一个标记,记录一下,当前位置产生的最长长度,然后倒着推len,len-1,len-2…1就好了

ll arr[maxn],cup[maxn],dp[maxn],vis[maxn];
ll p,n;
void solve(){
    
    n = read(), p = read();
    rep(i,1,n){
        vis[i] = 0;
        arr[i] = read();
        dp[i] = 0;
    }
    ll len = 0;
    rep(i,1,n){
        if(len == 0 || arr[i] > cup[len]){
            cup[++len] = arr[i];
            dp[i] = len;
        }else{
            int pos = lower_bound(cup+1,cup+len+1,arr[i])-cup;
            cup[pos] = arr[i];
            dp[i] = pos;
        }
    }
    ll tmp = len;
    ll ans = 0;
    per(i,n,1){
        if(dp[i]==tmp){
            tmp--;
            vis[i]=1;
            ans+=arr[i];
        }
    }
    cout<<ans+p<<endl;
    cout<<len<<endl;
    rep(i,1,n){
        if(vis[i]){
            cout<<i<<endl;
        }
    }
}

猜你喜欢

转载自blog.csdn.net/leoxe/article/details/106445085