Codeforces Round #259 (Div. 2)

传送门:http://codeforces.com/contest/454


这场比赛做的virtual,在家里面根本没法做CF,老妈连我白天碰一下电脑都要叨叨叨叨叨叨说半天,11点30做……简直hehe

出了3题,题数还行,但是B题WA太久了……不应该。


A题

一个简单的图形打印题,要求打印一个菱形,N为奇数,数好‘*’的个数,把图形分成两半打出来即可。


#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

int main(){
    int n;
    cin>>n;
    int std=(n+1)/2;
    for (int i=1;i<std;i++){
        for (int j=1;j<=std-i;j++) cout<<"*";
        for (int j=std-i+1;j<=n-(std-i);j++) cout<<"D";
        for (int j=1;j<=std-i;j++) cout<<"*";
        cout<<endl;
    }
    for (int i=1;i<=n;i++) cout<<"D";
    cout<<endl;
    for (int i=std-1;i>=1;i--){
    <span style="white-space:pre">	</span>for (int j=1;j<=std-i;j++) cout<<"*";
        for (int j=std-i+1;j<=n-(std-i);j++) cout<<"D";
        for (int j=1;j<=std-i;j++) cout<<"*";
        cout<<endl;
    }

    return 0;
}

B题

题目大意是给定一个序列,每次操作只能把最后一个数字移动到第一个位置,求最少多少次操作可以使得序列变为一个不下降序列。

抽象出来也即给一个环,找一个起点使得整个序列为不下降序列。


这道题貌似hack得相当欢乐,我第一次提交WA在了第二十多组数据上……一下子就无语了


首先,我们考虑有可行解的情况:因为要求是不下降序列,所以第一个元素一定是最小的那一个,假设这个最小值的位置是p(1..N编号),那么可以知道,要么p==1时,不动,要么p!=1时,移动n-p+1次。

所以,有解的情况是非常容易的。

接下来是判断无解,有两种想法:

1、最小值肯定是在要求生成序列的第一个,那么从最小值开始,把整个序列写出来,检查一次即可。第一次交就是这种方法,跪在了第22组测试数据,想必是hack的数据。很快想到了跪舔的原因,“不下降”暗示着元素是可以有相等的,当最小值出现多个时,应该以每一个都为起点检查一次(先检查后出现的最小值以保证步数最小),成功则直接输出,否则继续检查。但是考虑到极端情况(212121212121212121………………)的时间复杂度,GG。

2、现在的目的相当于是把这个数列砍成两段,然后把前一段放在后一段的后面,使得新生成的序列满足要求。

也就是说:(1)两段都是不下降序列(2)a[1]>=a[n]

===>满足(1)不下降序列超过2个(2)a[1]<a[n]中任意一个,都是无解的

时间复杂度很低,完全满足需求。


#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

int a[100000+20];

int main(){
    int n;
    cin>>n;
    for (int i=1;i<=n;i++){
        cin>>a[i];
    }

    a[n+1]=-1;

    int p=0;
    for (int i=1;i<=n;i++){
        if (a[i]>a[i+1]){
            p=i;
            break;
        }
    }

    if (p==n){
        cout<<0<<endl;
    }
    else {
        int flag=0;
        for (int i=p+1;i<n;i++){
            if (a[i]>a[i+1]){
                flag=1;
                break;
            }
        }

        if (flag==1){
            cout<<-1<<endl;
        }
        else {
            if (a[1]>=a[n]){
                cout<<n-p<<endl;
            }
            else {
                cout<<-1<<endl;
            }
        }
    }

    return 0;
}


C题

一个推公式的题,做得比较顺利,懒得传公式的图,直接代码表示:

  for(int i=1; i<=m; ++i) {
        sum = pow((i-1.0)/m, n*1.0);
        ans += (pow(i*1.0/m, n*1.0)-sum)*i;
    }

保留12位小数输出就行了。对于这种题,我只想说,幸好不是poj

#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <algorithm>
using namespace std;

int main(void) {
    int m, n;
    scanf("%d%d",&m,&n);
    double ans = 0.0;
    double sum = 0.0;
    for(int i=1; i<=m; ++i) {
        sum = pow((i-1.0)/m, n*1.0);
        ans += (pow(i*1.0/m, n*1.0)-sum)*i;
    }
    printf("%.12lf\n",ans);
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值