Codeforces Round #355 (Div. 2)

Codeforces Round #355 (Div. 2)


    说实在话,CF手快不及眼快,我题目意思还没读懂别人都写完了…冲1800的希望又破灭了…

A. Vanya and Fence

    大于h就是2,小于等于就是2,一个个加起来。

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

using namespace std;

int n,h,a[1005],ans;

int main()
{
    scanf("%d%d",&n,&h);
    for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    for (int i=1;i<=n;i++) if (a[i]>h) ans+=2;
    else ans++;
    printf("%d\n",ans);
    return 0;
}

B. Vanya and Food Processor

    这一题按照题目意思模拟就行了,注意结果要用long long。

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

using namespace std;

int n,h,a[100005],k;
long long ans;

int main()
{
    scanf("%d%d%d",&n,&h,&k);
    for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    int p=0,i=1,q;
    ans=0;
    while(i<=n)
    {
        while(p+a[i]<=h)
        {
            p+=a[i];
            i++;
        }
        q=(a[i]+p-h+k-1)/k;
        p=p-q*k;
        if (p<0) p=0;
        ans+=q;
    }
    ans+=(p+k-1)/k;
    printf("%I64d\n",ans);
    return 0;
}

C. Vanya and Label

    这题题目我就读了好半天…
    大致意思是有一个长度为n的串,因为每个字母都有一个值,如果两个串每一位的值都相同,我们就认为这两个串是相等的,现在让你求有多少组串:每组串按位且后与当前串相等。
    对于这题我们考虑按位处理,因为是且,所以我们只能在0上处理,对于每个0有三种情况(0,0)(0,1)(1,0),所以我们处理出每一位上的0有多少个在乘进结果就行了。
    答案同样是long long.

#include <iostream>
#include <cstring>
#include <cstdio>
#define mod 1000000007

using namespace std;

char s[100005];
int cos[7]={1,3,9,27,81,243,729};

int main()
{
    scanf("%s",s);
    int l=strlen(s),num=0;
    long long ans=1;
    for (int i=0;i<l;i++)
    {
        int cnt=0;
        if (s[i]=='-') num=62;
        else if (s[i]=='_') num=63;
        else if (s[i]>='0' && s[i]<='9') num=s[i]-'0';
        else if (s[i]>='A' && s[i]<='Z') num=s[i]-'A'+10;
        else num=s[i]-'a'+36;
        for (int j=0;j<6;j++) if ((num&(1<<j))==0) cnt++;
        ans=(ans*cos[cnt])%mod;
    }
    printf("%d\n",ans);
    return 0;
}

    读题读了这么久写完就这么点….


D. Vanya and Treasure

    这一题是说给你一个矩阵,里面有1,2….p,现在你一开始在(1,1)要你找到一条最短的路径从1,2…一直走到p。
    大概画出来就是一个明显的层次图,可以想到找到所有的i点,在找到所有的i+1,从i点推i+1。
    不过这种方法会超时,因为在枚举i和i+1的时候,个数的乘积可能会很大,所以,当这个乘积很大时我们不如直接对全图做一次SPFA,再把当前的解更新。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <queue>

using namespace std;

struct node
{
    int x,y;
    node(int x1,int y1):x(x1),y(y1){}
};
int way[4][2]={{0,1},{0,-1},{-1,0},{1,0}};
int n,m,p,a[305][305],d[305][305],dis[305][305];
bool flag[305][305];
vector<node> vec[90005];

int main()
{
    memset(d,0x3f,sizeof(d));
    int high=0;
    scanf("%d%d%d",&n,&m,&p);
    for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++)
        {
            scanf("%d",&a[i][j]);
            vec[a[i][j]].push_back(node(i,j));
        }
    for (int i=0;i<vec[1].size();i++)
    {
        int x=vec[1][i].x,y=vec[1][i].y;
        d[x][y]=x+y-2;
    }
    for (int i=2;i<=p;i++)
    {
        if (vec[i].size()*vec[i-1].size()<n*m)
        {
            for (int j=0;j<vec[i].size();j++)
            {
                int x1=vec[i][j].x,y1=vec[i][j].y;
                    for (int k=0;k<vec[i-1].size();k++)
                {
                    int x2=vec[i-1][k].x,y2=vec[i-1][k].y;
                    d[x1][y1]=min(d[x1][y1],d[x2][y2]+abs(x1-x2)+abs(y1-y2));
                }
            }
        }
        else
        {
            queue<node> Q;
            while(!Q.empty()) Q.pop();
            memset(dis,0x3f,sizeof(dis));
            memset(flag,0,sizeof(flag));
            for (int j=0;j<vec[i-1].size();j++)
            {
                dis[vec[i-1][j].x][vec[i-1][j].y]=d[vec[i-1][j].x][vec[i-1][j].y];
                Q.push(vec[i-1][j]);
                flag[vec[i-1][j].x][vec[i-1][j].y]=1;
            }
            while(!Q.empty())
            {
                node t=Q.front();
                Q.pop();
                flag[t.x][t.y]=0;
                for (int k=0;k<4;k++)
                {
                    int x=t.x+way[k][0],y=way[k][1]+t.y;
                    if (x>=1 && x<=n && y>=1 && y<=m && dis[t.x][t.y]+1<dis[x][y])
                    {
                        dis[x][y]=dis[t.x][t.y]+1;
                        if (!flag[x][y])
                        {
                            Q.push(node(x,y));
                            flag[x][y]=1;
                        }
                    }
                }
            }
            for (int j=1;j<=n;j++)
                for (int k=1;k<=m;k++) if (a[j][k]==i) d[j][k]=dis[j][k];
        }
    }
    int ans=0x7fffffff;
    for (int i=0;i<vec[p].size();i++)
    {
        int x=vec[p][i].x,y=vec[p][i].y;
        ans=min(ans,d[x][y]);
    }
    printf("%d\n",ans);
    return 0;
}

    这一题的复杂度我不是很懂,题解上给出的复杂度是 Onmnm ,感觉无法理解….
    这一题还有不少人使用2维线段树写的,个人感觉与这个迷之复杂度的程序相比,用2维线段树的做法要清晰的多。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值