Codeforces Round #355 (Div. 2) [Codeforces677]

28 篇文章 0 订阅
16 篇文章 0 订阅

此处有目录↑

Codeforces Round #355 (Div. 2):http://codeforces.com/contest/677


A. Vanya and Fence (模拟)

time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

Vanya and his friends are walking along the fence of height h and they do not want the guard to notice them. In order to achieve this the height of each of the friends should not exceed h. If the height of some person is greater than h he can bend down and then he surely won't be noticed by the guard. The height of the i-th person is equal to ai.

Consider the width of the person walking as usual to be equal to 1, while the width of the bent person is equal to 2. Friends want to talk to each other while walking, so they would like to walk in a single row. What is the minimum width of the road, such that friends can walk in a row and remain unattended by the guard?

Input

The first line of the input contains two integers n and h (1 ≤ n ≤ 10001 ≤ h ≤ 1000) — the number of friends and the height of the fence, respectively.

The second line contains n integers ai (1 ≤ ai ≤ 2h), the i-th of them is equal to the height of the i-th person.

Output

Print a single integer — the minimum possible valid width of the road.

Examples
input
3 7
4 5 14
output
4
input
6 1
1 1 1 1 1 1
output
6
input
6 5
7 6 8 9 10 5
output
11
Note

In the first sample, only person number 3 must bend down, so the required width is equal to 1 + 1 + 2 = 4.

In the second sample, all friends are short enough and no one has to bend, so the width 1 + 1 + 1 + 1 + 1 + 1 = 6 is enough.

In the third sample, all the persons have to bend, except the last one. The required minimum width of the road is equal to2 + 2 + 2 + 2 + 2 + 1 = 11.


题目大意:有n个数,若a[i]>h,则结果加上2;否则结果加上1,输出结果即可。

按照题意模拟即可

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

int n,h,ans;
int a;

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


B. Vanya and Food Processor (模拟)

time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

Vanya smashes potato in a vertical food processor. At each moment of time the height of the potato in the processor doesn't exceed hand the processor smashes k centimeters of potato each second. If there are less than k centimeters remaining, than during this second processor smashes all the remaining potato.

Vanya has n pieces of potato, the height of the i-th piece is equal to ai. He puts them in the food processor one by one starting from the piece number 1 and finishing with piece number n. Formally, each second the following happens:

  1. If there is at least one piece of potato remaining, Vanya puts them in the processor one by one, until there is not enough space for the next piece.
  2. Processor smashes k centimeters of potato (or just everything that is inside).

Provided the information about the parameter of the food processor and the size of each potato in a row, compute how long will it take for all the potato to become smashed.

Input

The first line of the input contains integers nh and k (1 ≤ n ≤ 100 000, 1 ≤ k ≤ h ≤ 109) — the number of pieces of potato, the height of the food processor and the amount of potato being smashed each second, respectively.

The second line contains n integers ai (1 ≤ ai ≤ h) — the heights of the pieces.

Output

Print a single integer — the number of seconds required to smash all the potatoes following the process described in the problem statement.

Examples
input
5 6 3
5 4 3 2 1
output
5
input
5 6 3
5 5 5 5 5
output
10
input
5 6 3
1 2 1 1 1
output
2
Note

Consider the first sample.

  1. First Vanya puts the piece of potato of height 5 into processor. At the end of the second there is only amount of height 2 remaining inside.
  2. Now Vanya puts the piece of potato of height 4. At the end of the second there is amount of height 3 remaining.
  3. Vanya puts the piece of height 3 inside and again there are only 3 centimeters remaining at the end of this second.
  4. Vanya finally puts the pieces of height 2 and 1 inside. At the end of the second the height of potato in the processor is equal to 3.
  5. During this second processor finally smashes all the remaining potato and the process finishes.

In the second sample, Vanya puts the piece of height 5 inside and waits for 2 seconds while it is completely smashed. Then he repeats the same process for 4 other pieces. The total time is equal to 2·5 = 10 seconds.

In the third sample, Vanya simply puts all the potato inside the processor and waits 2 seconds.


题目大意:给定n个高度不同的土豆,按照顺序叠加在一起,若叠加后的高度不超过h,则当前必定叠加,否则花费1s去掉高度为k的土豆(不足k时也需要花费1s),求最后将土豆都切掉时的用时?

按照题意模拟即可,样例已经给出了:当前土豆高度不超过k,但不能叠加下一个土豆(这种情况也需要花费1s)。所以样例过了基本就能AC

好久不写题,又被叉long long了...

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

long long n,h,k,ans,cur,a;

int main() {
    while(3==scanf("%I64d%I64d%I64d",&n,&h,&k)) {
        ans=cur=0;
        for(int i=0;i<n;++i) {
            scanf("%I64d",&a);
            if(cur+a<=h) {
                cur+=a;
            }
            else {
                ans+=cur/k;
                cur%=k;
                if(cur+a<=h) {
                    cur+=a;
                }
                else {
                    ++ans;
                    cur=a;
                }
            }
        }
        if(cur>=k) {
            ans+=cur/k;
            cur%=k;
        }
        ans+=cur>0?1:0;
        printf("%I64d\n",ans);

    }
    return 0;
}

C. Vanya and Label (模拟&&快速幂)

time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

While walking down the street Vanya saw a label "Hide&Seek". Because he is a programmer, he used & as a bitwise AND for these two words represented as a integers in base 64 and got new word. Now Vanya thinks of some string s and wants to know the number of pairs of words of length |s| (length of s), such that their bitwise AND is equal to s. As this number can be large, output it modulo 109 + 7.

To represent the string as a number in numeral system with base 64 Vanya uses the following rules:

  • digits from '0' to '9' correspond to integers from 0 to 9;
  • letters from 'A' to 'Z' correspond to integers from 10 to 35;
  • letters from 'a' to 'z' correspond to integers from 36 to 61;
  • letter '-' correspond to integer 62;
  • letter '_' correspond to integer 63.
Input

The only line of the input contains a single word s (1 ≤ |s| ≤ 100 000), consisting of digits, lowercase and uppercase English letters, characters '-' and '_'.

Output

Print a single integer — the number of possible pairs of words, such that their bitwise AND is equal to string s modulo 109 + 7.

Examples
input
z
output
3
input
V_V
output
9
input
Codeforces
output
130653412
Note

For a detailed definition of bitwise AND we recommend to take a look in the corresponding article in Wikipedia.

In the first sample, there are 3 possible solutions:

  1. z&_ = 61&63 = 61 = z
  2. _&z = 63&61 = 61 = z
  3. z&z = 61&61 = 61 = z


题目大意:给定一个位数不超过100 000 的 64进制的数s,求有多少对数的a,b使得a&b=s(有序)?

大致思路:将64进制的数转成2进制表示,则每一位64进制数对应6位2进制数(当时脑抽,算都没算就认为是8位,调试了半天才发现...)

对每一位二进制数:①结果为1的只有一种情况:1&1;②结果为0的有3中情况:0&0,0&1,1&0

所以只需要统计结果中二进制位为0的位数cnt,则答案为:3^cnt  (貌似不用快速幂也不会TLE)

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

int num;
char s[100005];
long long ans,cnt;

const long long MOD=1e9+7;

int ch2num(char ch) {
    if('0'<=ch&&ch<='9') {
        return ch-'0';
    }
    if('A'<=ch&&ch<='Z') {
        return ch-'A'+10;
    }
    if('a'<=ch&&ch<='z') {
        return ch-'a'+36;
    }
    return ch=='-'?62:63;
}

long long quickpow(long long m,long long n) {
    long long b = 1;
    while (n > 0) {
        if (n & 1)
            b = (b*m)%MOD;
        n = n >> 1 ;
        m = (m*m)%MOD;
    }
    return b;
}

int main() {
    while(1==scanf("%s",s)) {
        ans=cnt=0;
        for(int i=0;s[i]!='\0';++i) {
            num=ch2num(s[i]);
            for(int i=0;i<6;++i) {
                if((num&1)==0) {
                    ++cnt;
                }
                num>>=1;
            }
        }
        printf("%I64d\n",quickpow(3,cnt));
    }
    return 0;
}

————————————————— —3题的旅游分割线—————— —————————————

D. Vanya and Treasure (分类)

time limit per test
1.5 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Vanya is in the palace that can be represented as a grid n × m. Each room contains a single chest, an the room located in the i-th row and j-th columns contains the chest of type aij. Each chest of type x ≤ p - 1 contains a key that can open any chest of type x + 1, and all chests of type 1 are not locked. There is exactly one chest of type p and it contains a treasure.

Vanya starts in cell (1, 1) (top left corner). What is the minimum total distance Vanya has to walk in order to get the treasure? Consider the distance between cell (r1, c1) (the cell in the row r1 and column c1) and (r2, c2) is equal to |r1 - r2| + |c1 - c2|.

Input

The first line of the input contains three integers nm and p (1 ≤ n, m ≤ 300, 1 ≤ p ≤ n·m) — the number of rows and columns in the table representing the palace and the number of different types of the chests, respectively.

Each of the following n lines contains m integers aij (1 ≤ aij ≤ p) — the types of the chests in corresponding rooms. It's guaranteed that for each x from 1 to p there is at least one chest of this type (that is, there exists a pair of r and c, such that arc = x). Also, it's guaranteed that there is exactly one chest of type p.

Output

Print one integer — the minimum possible total distance Vanya has to walk in order to get the treasure from the chest of type p.

Examples
input
3 4 3
2 1 1 1
1 1 1 1
2 1 1 3
output
5
input
3 3 9
1 3 5
8 9 7
4 6 2
output
22
input
3 4 12
1 2 3 4
8 7 6 5
9 10 11 12
output
11

题目大意:给定一个n*n的地图,每个点(i,j)有一个类型为g[i][j]的箱子,共有p种类型的箱子(1~p,且p类型箱子只有一个)每个类型为x的箱子内有一把能打开类型为x+1的箱子的钥匙,初始类型为1的箱子均打开,且人在(1,1),求打开p类型箱子时所需走的最小距离?


已经想到按类型分点,然后枚举相邻的类型,脑内闪过一下错误的时间复杂度就开始写了,完全没注意正确的应该是:O(n^2*m^2),只枚举的话肯定会TLE,TLE on pretest 19才知道要放弃...

看了题解后,发现本题需要分类求解以降低时间复杂度,第一次遇到这种题,感觉好神奇

大致是:设相邻两种类型的箱子数分别为x,y

①x*y<n*m:则直接枚举即可,一次复杂度为:O(n*m)

②x*y>=n*m:则进行BFS搜索即可,一次复杂度为:O(n*m)


感觉总复杂度是这样得出来的:

由于只有n*m个点,所以最多有n*m/(2*sqrt(n*m))=1/2*sqrt(n*m)次复杂度为O(n*m)的运算

所以总复杂度为:O(n*m*sqrt(n*m))


刚开始用优先队列,结果多了个O(log(n*m)),TLE on test 18后才仔细看题解的BFS方法

感觉题解的BFS方法也很巧妙(需要每次增加的幅度均为1,才能保证升序),对初始点按照距离升序排序,初始只将第一个点放入队列  

然后每次更新队首的点之前,将距离小于等于队首的点的距离的初始点放入队列,这样就保证了队列中的点的距离是升序的

#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>

using namespace std;

struct Node {
    int r,c,w;

    Node(int rr=0,int cc=0,int ww=0):r(rr),c(cc),w(ww) {}

    bool operator < (const Node& a) const {
        return w<a.w;
    }
}q[900005];

int n,m,p,r,c,pr,pc,tmp;
int g[305][305],mn[305][305],head,tail,index;//g[i][j]表示点(i,j)的类型,mn[i][j]表示从(1,1)到(i,j)的最短距离
bool vis[305][305];
vector<Node> cur[900005];//cur[i]表示类型为i的点的数组

const int dr[4]={-1,0,1,0};
const int dc[4]={0,1,0,-1};

inline bool isInside(int rr,int cc) {
    return 1<=rr&&rr<=n&&1<=cc&&cc<=m;
}

void bfs(int sta) {
    int rr,cc,ww,des=sta+1;
    head=tail=index=0;
    memset(vis,false,sizeof(vis));
    for(int i=cur[sta].size()-1;i>=0;--i) {//给每个类型为sta的点的距离赋其实际需要的距离
        cur[sta][i].w=mn[cur[sta][i].r][cur[sta][i].c];
    }
    sort(cur[sta].begin(),cur[sta].end());

    vis[cur[sta][index].r][cur[sta][index].c]=true;
    q[tail].r=cur[sta][index].r;
    q[tail].c=cur[sta][index].c;
    q[tail++].w=cur[sta][index++].w;//距离最小的元素放进队列

    while(head!=tail) {
        r=q[head].r;
        c=q[head].c;
        ww=q[head++].w;
        if(g[r][c]==des) {
            mn[r][c]=ww;
        }
        while(index<cur[sta].size()&&cur[sta][index].w<=ww) {//如果存在类型为i的点的距离小于等于当前bfs已经更新到的距离,则将其入队
            vis[cur[sta][index].r][cur[sta][index].c]=true;
            q[tail].r=cur[sta][index].r;
            q[tail].c=cur[sta][index].c;
            q[tail++].w=cur[sta][index++].w;
        }
        ++ww;
        for(int i=0;i<4;++i) {//更新当前点周围四个点的距离
            rr=r+dr[i];
            cc=c+dc[i];
            if(isInside(rr,cc)&&!vis[rr][cc]) {
                vis[rr][cc]=true;
                q[tail].r=rr;
                q[tail].c=cc;
                q[tail++].w=ww;
            }
        }

    }
}

int main() {
    while(3==scanf("%d%d%d",&n,&m,&p)) {
        tmp=n*m;
        for(int i=p;i>=0;--i) {
            cur[i].clear();
        }
        for(int i=1;i<=n;++i) {
            for(int j=1;j<=m;++j) {
                scanf("%d",&g[i][j]);
                mn[i][j]=0x3f3f3f3f;
                cur[g[i][j]].push_back(Node(i,j));
            }
        }
        for(int j=cur[1].size()-1;j>=0;--j) {//类型1的点所需距离为r-1+c-1
            r=cur[1][j].r;
            c=cur[1][j].c;
            mn[r][c]=r+c-2;
        }
        for(int i=2;i<=p;++i) {
            if(1LL*cur[i-1].size()*cur[i].size()>=tmp) {
                bfs(i-1);//bfs更新类型i的点的最短距离
            }
            else {
                for(int j=cur[i].size()-1;j>=0;--j) {//枚举更新类型i的点的最短距离
                    r=cur[i][j].r;
                    c=cur[i][j].c;
                    for(int k=cur[i-1].size()-1;k>=0;--k) {
                        pr=cur[i-1][k].r;
                        pc=cur[i-1][k].c;
                        mn[r][c]=min(mn[r][c],mn[pr][pc]+abs(r-pr)+abs(c-pc));
                    }
                }
            }
        }
        printf("%d\n",mn[cur[p][0].r][cur[p][0].c]);
    }
    return 0;
}


E. Vanya and Balloons (DP预处理)

time limit per test
3 seconds
memory limit per test
512 megabytes
input
standard input
output
standard output

Vanya plays a game of balloons on the field of size n × n, where each cell contains a balloon with one of the values 012 or 3. The goal is to destroy a cross, such that the product of all values of balloons in the cross is maximum possible. There are two types of crosses: normal and rotated. For example:

**o**
**o**
ooooo
**o**
**o**

or

o***o
*o*o*
**o**
*o*o*
o***o

Formally, the cross is given by three integers rc and d, such that d ≤ r, c ≤ n - d + 1. The normal cross consists of balloons located in cells (x, y) (where x stay for the number of the row and y for the number of the column), such that |x - r|·|y - c| = 0 and|x - r| + |y - c| < d. Rotated cross consists of balloons located in cells (x, y), such that |x - r| = |y - c| and |x - r| < d.

Vanya wants to know the maximum possible product of the values of balls forming one cross. As this value can be large, output it modulo 109 + 7.

Input

The first line of the input contains a single integer n (1 ≤ n ≤ 1000) — the number of rows and columns in the table with balloons.

The each of the following n lines contains n characters '0', '1', '2' or '3' — the description of the values in balloons.

Output

Print the maximum possible product modulo 109 + 7. Note, that you are not asked to maximize the remainder modulo 109 + 7, but to find the maximum value and print it this modulo.

Examples
input
4
1233
0213
2020
0303
output
108
input
5
00300
00300
33333
00300
00300
output
19683
input
5
00003
02030
00300
03020
30000
output
108
input
5
21312
10003
10002
10003
23231
output
3
input
5
12131
12111
12112
21311
21212
output
24
Note

In the first sample, the maximum product is achieved for a rotated cross with a center in the cell (3, 3) and radius 12·2·3·3·3 = 108.


题目大意:给定一个n*n的格子,每一小个有一个数字0~3,可以以(i,j)为中心取一个十字(正十字或斜十字),该十字的四个分支的长度必须相等,每个十字或得的结果为各个格子内数字的乘积,求该乘积的最大值?

大致思路:首先可以想到需要枚举以每一个格子为中心,然后获取其最大值,则答案为这些最大值的最大值,直接枚举是O(n*3),就超超时了

由于要使结果最大,则十字中必定不含0,所以需要预处理出以每一个格子为中心,在8个方向上能延伸出去的最大长度

又:求(i,j)点k方向能延伸的最大长度时,(i+dr[k],j+dc[k])点k方向能延伸的最大长度已经求出,且后者能推出前者,所以这个可以用dp在O(n^2)内求出

然后再枚举以(i,j)点为中心时,可以在O(1)内求出其最大值

所以总的时间复杂度为O(n^2)

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>

using namespace std;

int n,ii,jj,mx,ans_i,ans_j,ans_type,ans_mx;
char s[1005][1005];
int cnt[1005][1005][8];//0~7分别代表左,左上,正上,右上;右,右下,正下,左下;cnt[i][j][k]表示点(i,j)开始在k方向上能走多远
double sum[1005][1005][4];//0~4分别代表左,左上,正上,右上;sum[i][j][k]表示点(i,j)开始在k方向走到头时,每一点对应的log的和
double lg[5],tmp,ans;
long long res;

const int dr[8]={0,-1,-1,-1,0,1,1,1};
const int dc[8]={-1,-1,0,1,1,1,0,-1};
const long long MOD=1e9+7;

int main() {
    lg[0]=lg[1]=0;
    lg[2]=log(2.0);
    lg[3]=log(3.0);
    while(1==scanf("%d",&n)) {
        memset(cnt,0,sizeof(cnt));
        memset(sum,0,sizeof(sum));
        for(int i=1;i<=n;++i) {
            scanf("%s",&s[i][1]);
        }
        for(int i=1;i<=n;++i) {
            for(int j=1;j<=n;++j) {
                if(s[i][j]!='0') {
                    for(int k=0;k<4;++k) {//0~3的方向从左上角开始更新
                        cnt[i][j][k]=cnt[i+dr[k]][j+dc[k]][k]+1;
                        sum[i][j][k]=sum[i+dr[k]][j+dc[k]][k]+lg[s[i][j]-'0'];
                    }
                }
                ii=n-i+1;
                jj=n-j+1;
                if(s[ii][jj]!='0') {
                    for(int k=4;k<8;++k) {//4~7的方向从右下角开始更新
                        cnt[ii][jj][k]=cnt[ii+dr[k]][jj+dc[k]][k]+1;
                    }
                }
            }
        }

        ans=ans_mx=ans_type=0;
        ans_i=ans_j=1;
        for(int i=1;i<=n;++i) {
            for(int j=1;j<=n;++j) {
                if(s[i][j]!='0') {
                    mx=min(min(cnt[i][j][0],cnt[i][j][2]),min(cnt[i][j][4],cnt[i][j][6]));//正着十字能延伸的最大
                    tmp=sum[i][j+mx-1][0]-sum[i][j-mx][0]+sum[i+mx-1][j][2]-sum[i-mx][j][2]-lg[s[i][j]-'0'];
                    if(ans<tmp) {
                        ans=tmp;
                        ans_i=i;
                        ans_j=j;
                        ans_type=0;
                        ans_mx=mx;
                    }
                    mx=min(min(cnt[i][j][1],cnt[i][j][3]),min(cnt[i][j][5],cnt[i][j][7]));//斜着十字能延伸的最大
                    tmp=sum[i+mx-1][j+mx-1][1]-sum[i-mx][j-mx][1]+sum[i+mx-1][j-mx+1][3]-sum[i-mx][j+mx][3]-lg[s[i][j]-'0'];
                    if(ans<tmp) {
                        ans=tmp;
                        ans_i=i;
                        ans_j=j;
                        ans_type=1;
                        ans_mx=mx;
                    }
                }
            }
        }

        res=s[ans_i][ans_j]-'0';
        for(int k=0;k<=6;k+=2) {
            for(int l=1;l<ans_mx;++l) {
                res=(res*(s[ans_i+l*dr[ans_type+k]][ans_j+l*dc[ans_type+k]]-'0'))%MOD;
            }
        }
        printf("%I64d\n",res);
    }
    return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值