Codeforces Round #136 (Div. 2)

第一题:Little Elephant and Function

题意:通过不断调用一个交换函数可以把一个数字序列变成升序,问原始的数字序列是什么。

题解:逆向模拟即可。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int num[1005];
int n;
void f(int x)
{
    if(x>n) return;
    f(x+1);
    swap(num[x-1],num[x]);
}
int main()
{
    scanf("%d",&n);
    if(n==1)
    {
        printf("1\n");
        return 0;
    }
    for(int i=1;i<=n;++i) num[i]=i;
    f(2);
    for(int i=1;i<=n;++i)
        if(i==1) printf("%d",num[i]);
        else     printf(" %d",num[i]);
    puts("");
    return 0;
}

第二题:Little Elephant and Numbers

题意:给你一个数N,要求找出数d,d能整除N,同时d和N至少包含一个相同的数字,问这样的d有多少个。

题解:求出N的因子,再判断有多个因子符合要求。

代码:

#include<cstdio>
#include<cstring>
using namespace std;
bool flag[11];
bool check(int x)
{
    for(int i=x;i>0;i/=10) if(flag[i%10]) return true;
    return false;
}
int main()
{
   int n,summ=0;
   scanf("%d",&n);
   memset(flag,false,sizeof(flag));
   for(int i=n;i>0;i/=10) flag[i%10]=true;
   for(int i=1;i*i<=n;++i)
   {
       if(n%i==0)
       {
           if(check(i)) summ++;
           if(i==n/i) continue;
           if(check(n/i)) summ++;
       }
   }
   printf("%d\n",summ);
   return 0;
}

第三题:Little Elephant and Problem

题意:给出一个数组,问是否是由一个已排序的数组经过交换至多一对数得到。

题解:将给定的数组排序后与元数组比较,若有多于两个位置不同则输出“YES”,否则将原数组两个位置的数字交换后比较是否与排序后数组相同。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int a[100005],b[100005];
int cnt[3];
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;++i)
    {
        scanf("%d",a+i);
        b[i]=a[i];
    }
    sort(b,b+n);
    int ans=0;
    for(int i=0;i<n;++i)
    {
        if(a[i]!=b[i])
        {
            if(ans>=2)
            {
                puts("NO");
                return 0;
            }
            cnt[ans++]=i;
        }
    }
    if(ans<1)
        puts("YES");
    else
    {
        if(a[cnt[0]]==b[cnt[1]]&&a[cnt[1]]==b[cnt[0]])
           puts("YES");
        else
           puts("NO");
    }
    return 0;
}

第四题:Little Elephant and Array

题意:一个n个数字的数字序列,同时有m次询问,问在a,b之间符合数字x刚好出现x次的数有多少个。

题解:由于符合条件的数总数不超过450个,我们可以从此下手,先统计每个数字出现的次数,剔除不可能符合条件的数字,然后h[i][j]表示第i个数字在0~j出现的次数,询问的时候只要对i个数字将0~a-1和0~b两个区间内第i个数出现的次数相减就得到第i个数字在a~b中出现的次数,统计即可。

代码:

#include<cstdio>
#include<cstring>
#include<map>
#define MAX 100005
using namespace std;
struct node
{
    int x,num;
} temp;
int s[MAX],b[450],h[MAX][450];
map<int,struct node> mat;
int main()
{
    int n,m,k,t;
    for(; ~scanf("%d%d",&n,&t);)
    {
        mat.clear();
        for(int i=1; i<=n; ++i)
        {
            scanf("%d",&s[i]);
            //统计一个数出现的次数
            if(mat.count(s[i])==0)
            {
                temp.x=s[i];
                temp.num=1;
                mat.insert(make_pair(s[i],temp));
            }
            else
                (mat.find(s[i])->second.num)++;
        }
        k=0;
        //查找可能符合条件的数
        for(map<int,struct node>::iterator it=mat.begin(); it!=mat.end(); ++it)
            if(it->second.x<=it->second.num)  b[++k]=it->second.x;
        for (int i=1; i<=k; ++i)
        {
            h[0][i]=0;
            for (int j=1; j<=n; ++j)
                if (s[j]==b[i]) h[j][i]=h[j-1][i]+1;
                else            h[j][i]=h[j-1][i];
        }
        int l,r,ans;
        for(;t--;)
        {
            ans=0;
            scanf("%d%d",&l,&r);
            for (int i=1; i<=k; ++i)
                if (h[r][i]-h[l-1][i]==b[i]) ans++;
            printf("%d\n",ans);
        }
    }
    return 0;
}

第五题: Little Elephant and Shifts

题意:给你一个1~n组成的n个数字的数列a,再给一个a数列的另一种排序方式形成的数列b,两个数列的距离为最小的|i - j|ai = bj问将b循环左移n次,每次循环左移后a与b的距离是多少。

题解:每次求的最小距离都是最大的负数与最小的非负数中绝对值最小的一个。

代码:

#include<cstdio>
#include<algorithm>
#include<set>
using namespace std;
#define MAX 100010
int a[MAX],b[MAX],hashx[MAX],d[MAX];
multiset<int> s;
int main()
{
    int n,t,res;
    scanf("%d",&n);
    for(int i=0; i<n; ++i)
    {
        scanf("%d",a+i);
        hashx[a[i]]=i;//存放数字在a中的位置
    }
    for(int i=0; i<n; ++i)
    {
        scanf("%d",b+i);
        s.insert(i-hashx[b[i]]);//插入相同数字的距离
    }
    for(int i=0; i<n; ++i)
    {
        multiset<int>::iterator it=s.lower_bound(i);//查找大于等于i的第一个数
        res=0xfffff;
        if(it!=s.end())   res=min(res,(*it)-i);//非负数中最小的数的绝对值
        if(it!=s.begin()) res=min(res,i-(*(--it)));//负数中的最大的数的绝对值
        printf("%d\n",res);
        //模拟旋转
        t=b[i];
        s.erase(s.find(i-hashx[t]));
        s.insert((i+n)-hashx[t]);
    }
    return 0;
}


来源:http://blog.csdn.net/acm_ted/article/details/7943188


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值