第一次比赛(续)

codeforce 527A Playing with Paper


问题描述:

One day Vasya was sitting on a not so interesting Maths lesson and making an origami from a rectangular a mm  × b mm sheet of paper (a > b). Usually the first step in making an origami is making a square piece of paper from the rectangular sheet by folding the sheet along the bisector of the right angle, and cutting the excess part.



After making a paper ship from the square piece, Vasya looked on the remaining (a - b) mm  × b mm strip of paper. He got the idea to use this strip of paper in the same way to make an origami, and then use the remainder (if it exists) and so on. At the moment when he is left with a square piece of paper, he will make the last ship from it and stop.

Can you determine how many ships Vasya will make during the lesson?

Input
The first line of the input contains two integers a, b (1 ≤ b < a ≤ 1012) — the sizes of the original sheet of paper.

Output
Print a single integer — the number of ships that Vasya will make.

Sample Input
Input
2 1
Output
2
Input
10 7
Output
6
Input
1000000000000 1
Output

1000000000000

AC代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
    long long a,b;
    while(scanf("%I64d %I64d",&a,&b)!=EOF)
    {
        long long sum=0;
        while(a != 0 && b != 0)
        {
            sum += (a / b);
            a %= b;
            if(a < b)
                swap(a,b);
        }
        printf("%I64d\n",sum);
    }
    return 0;
}
codeforce 527B
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Ford Prefect got a job as a web developer for a small company that makes towels. His current work task is to create a search engine for the website of the company. During the development process, he needs to write a subroutine for comparing strings S and T of equal length to be "similar". After a brief search on the Internet, he learned about the Hamming distance between two strings S and T of the same length, which is defined as the number of positions in which S and T have different characters. For example, the Hamming distance between words "permanent" and "pergament" is two, as these words differ in the fourth and sixth letters.

Moreover, as he was searching for information, he also noticed that modern search engines have powerful mechanisms to correct errors in the request to improve the quality of search. Ford doesn't know much about human beings, so he assumed that the most common mistake in a request is swapping two arbitrary letters of the string (not necessarily adjacent). Now he wants to write a function that determines which two letters should be swapped in string S, so that the Hamming distance between a new string S and string T would be as small as possible, or otherwise, determine that such a replacement cannot reduce the distance between the strings.

Help him do this!
Input

The first line contains integer n (1 ≤ n ≤ 200 000) — the length of strings S and T.

The second line contains string S.

The third line contains string T.

Each of the lines only contains lowercase Latin letters.
Output

In the first line, print number x — the minimum possible Hamming distance between strings S and T if you swap at most one pair of letters in S.

In the second line, either print the indexes i and j (1 ≤ i, j ≤ n, i ≠ j), if reaching the minimum possible distance is possible by swapping letters on positions i and j, or print "-1 -1", if it is not necessary to swap characters.

If there are multiple possible answers, print any of them.
Sample test(s)
Input

9
pergament
permanent

Output

1
4 6

Input

6
wookie
cookie

Output

1
-1 -1

Input

4
petr
egor

Output

2
1 2

Input

6
double
bundle

Output

2
4 1
题目大意:给你两个长度相同的字符串 A,B 现要求你交换A串中两个位置的字符,使得A B串对应位置不相同的次数最小。输出改变后两个字符串还有多少字符不同,以及改变的位置。如果不需要改变,则输出 -1 ,-1
解题思路:
因为只能交换两个位置, 所以不同的次数只可能减小 0 , 1, 2。 用 p[ i ][ j ]保存 不相同位置A串中元素与B串中元素 i 代表A串中字符 j代表B串字符。
① 当存在p [ i ][ j ] == p [ j ][ i ], 则可以减小 2
② 当①不满足,若存在 p[ i ][ j ] == p[ j ] [ k ],则可以减小1
③ 不能减小
AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxm = 200000 + 10;
const int maxn = 26;
int a[maxn][maxn];
char s[maxm];
char t[maxm];
int main()
{
    int n;
    while(scanf("%d",&n) != EOF)
    {
        scanf("%s %s",s,t);
        getchar();
        memset(a,0,sizeof(a));
        int cnt = 0;
        for(int i = 0;i < n;i++)
        {
            if(s[i] != t[i])
            {
                a[s[i] - 'a'][t[i] - 'a'] = i + 1;
                cnt++;
            }
        }
        int flag = 0;
        int r,g;
        for(int i = 0;i < maxn;i++)
            for(int j = 0;j < maxn;j++)
                if((r = a[i][j]) && (g = a[j][i]))
                    flag = 2,i = j = maxn;
        if(!flag)
        {
            for(int i = 0;i < maxn;i++)
                for(int j = 0;j < maxn;j++)
                    for(int k = 0;k < maxn;k++)
                        if((r = a[i][j]) && (g = a[j][k]))
                            flag = 1,i = j = k = maxn;
        }
        if(!flag)
            r = g = -1;
        printf("%d\n%d %d\n",cnt - flag,r,g);
    }
    return 0;
}
<h1 style="margin: 0px; padding: 0px; color: rgb(54, 46, 43); font-family: Arial; line-height: 26px;">codeforce 527c</h1>
Leonid wants to become a glass carver (the person who creates beautiful artworks by cutting the glass). He already has a rectangular w mm  × h mm sheet of glass, a diamond glass cutter and lots of enthusiasm. What he lacks is understanding of what to carve and how.

In order not to waste time, he decided to practice the technique of carving. To do this, he makes vertical and horizontal cuts through the entire sheet. This process results in making smaller rectangular fragments of glass. Leonid does not move the newly made glass fragments. In particular, a cut divides each fragment of glass that it goes through into smaller fragments.

After each cut Leonid tries to determine what area the largest of the currently available glass fragments has. Since there appear more and more fragments, this question takes him more and more time and distracts him from the fascinating process.

Leonid offers to divide the labor — he will cut glass, and you will calculate the area of the maximum fragment after each cut. Do you agree?

Input
The first line contains three integers w, h, n (2 ≤ w, h ≤ 200 000, 1 ≤ n ≤ 200 000).

Next n lines contain the descriptions of the cuts. Each description has the form H y or V x. In the first case Leonid makes the horizontal cut at the distance y millimeters (1 ≤ y ≤ h - 1) from the lower edge of the original sheet of glass. In the second case Leonid makes a vertical cut at distance x (1 ≤ x ≤ w - 1) millimeters from the left edge of the original sheet of glass. It is guaranteed that Leonid won't make two identical cuts.

Output
After each cut print on a single line the area of the maximum available glass fragment in mm2.

Sample Input
Input
4 3 4
H 2
V 2
V 3
V 1
Output
8
4
4
2
Input
7 6 5
H 4
V 3
V 5
H 2
V 1
Output
28
16
12
6
4

解题思路:
可以看出经过n次切割之后,剩余的最大面积就是剩余部分长的最大值mh和 宽ms的最大值。 所以我们可用multiset储存切割后的长宽即可。

每次切割都要用set记录,且寻找切点两边的边界,这样才能计算出新的长或宽,还要删除旧的长和宽。
AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<set>
using namespace std;
const int maxn = 200000 + 10;
int main()
{
    int w,h,n;
    set<int>sh;//用来存储切点
    set<int>sw;//用来存储切点
    multiset<int >mh;//用来存储高
    multiset<int >mw;//用来存储宽
    while(scanf("%d%d%d",&w,&h,&n) != EOF)
    {
        sh.clear();sw.clear();
        mh.clear();mw.clear();
        sh.insert(0);
        sh.insert(h);//初始切点加入
        sw.insert(0);
        sw.insert(w);
        mh.insert(h);
        mw.insert(w);//初始长度加入
        char order;
        int pos;
        while(n--)
        {
            cin >> order >> pos;
            if(order == 'H')
            {
                sh.insert(pos);
                int a = *(--sh.find(pos));//寻找切点的上下两条切点
                int b = *(++sh.find(pos));
                mh.erase(mh.find(b - a));// mh.erase(b-a); //这里注意不能这样删除,否则就将所有元素中等于 b - a 的都删除了
                mh.insert(b - pos);
                mh.insert(pos - a);
            }
            else
            {
                sw.insert(pos);
                int a = *(--sw.find(pos));
                int b = *(++sw.find(pos));
                mw.erase(mw.find(b - a));//在multiset中删除旧的长或宽
                mw.insert(b - pos); // 插入新的长或宽
                mw.insert(pos - a);
            }
            printf("%I64d\n",(long long)(*(--mh.end()))*(*(--mw.end())));
        }
    }
    return 0;
}
问题描述:FZU 2202
Description

福尔摩斯是个大侦探,他总是在解决疑难案件。这一次的案件也不例外,案件是这样的:有编号为1到N的N位嫌疑犯,他们其中有一个犯了罪,然后每个嫌疑犯都被询问,“哪一个人犯了罪?”犯罪嫌疑人的答案只能“编号ai的嫌疑犯犯了罪”或者“编号ai的嫌疑犯没有犯罪”。当然嫌疑犯也可以说他自己(ai = i).

福尔摩斯凭着他敏锐的侦探直觉,确定地对华生说,只有M个人说了真话,其余人都是说谎。然后就没有然后了,但华生却想知道哪些人说谎哪些人又是讲真话。这个时候同样聪明的你,被誉为红旗下的名侦探是否愿意秀一下自己的侦探天赋,帮助可怜的华生嘛?

Input

第一行一个整数T(1 <= T <= 10),表示测试数据的组数。

每组数据第一行包含N(1 <= N <=10^5)和M(0 <= M <= N)两个整数,含义见题面。接下来N行,第i行是一个整数+ai或者-ai(1<= ai <= N),如果是+ai,代表第i个人说编号ai犯了罪,如果是-ai,则表示编号ai没有犯罪。

输入数据保证至少存在一个人,使得如果是他犯了罪,则恰好有 M 个人说了真话。

Output

输出为N行,第i行是第i个嫌疑犯的输出。如果第i个嫌疑犯说了是真话,输出“Truth”;如果说谎,则输出“Lie”,如果不确定,则输出“Not defined”。

Sample Input
2
3 2
-1
-2
-3
4 1
+2
-3
+4
-1

Sample Output
Not defined
Not defined
Not defined
Lie
Not defined
Lie
Not defined
解题思路:对于每个人i,如果他被指控,则a[i]++;

如果他被澄清,则b[i]++;

然后统计总人数中,澄清的语句的条数s。

那么对于i来说,如果i是罪犯,那么真话数s=a[i]+s2-b[i]。

那么我们就可以判断出这个人是否是嫌疑犯了。依据这个我们可以知道哪些人是嫌疑犯。

如果已经确定的嫌疑犯只有一个,那么这个人就是罪犯了,这样所有人说的话是真是假就很容易知道了。

如果已经确定的嫌疑犯有多个,对每一个人i说得话x[i]进行判断:

如果x[i]是正数,那么就看x[i]是否是嫌疑犯,如果是则i说的话难以确定,否则表明i说的是假话。

如果x[i]是负数,那么就看x[i]是否是嫌疑犯,如果不是则i说的难以确定,否则表明i说的是真话
AC代码:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 120000 + 5;
int vis[maxn],p[maxn],a[maxn],b[maxn],x[maxn];//a[i]被指控,b[i]被澄清
int main()
{
    int T,j,k,n,m,s1,s2;
    scanf("%d",&T);
    while(T--)
    {
        memset(vis,0,sizeof(vis));
        memset(p,0,sizeof(p));
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        memset(x,0,sizeof(x));
        s1 = 0, s2 = 0;
        scanf("%d%d",&n,&m);
        for(int i = 1;i <= n;i++)
        {
            cin >> x[i];
            if(x[i] > 0){a[x[i]]++;s1++;}
            else if(x[i]<0){b[-x[i]]++;s2++;}
        }
        int t = 0;
        for(int i = 1;i <= n;i++)
        {
            int s = a[i] + s2 - b[i];//统计总人数中,澄清的语句的条数s。那么对于i来说,如果i是罪犯,那么真话数x=a[i]+s-b[i]。
            if(s == m)
                {vis[i] = 1;t++;}
        }
        if(t == 1)
        {
            for(int i = 1;i <= n;i++)
            {
                if(x[i] > 0)
                {
                    if(vis[x[i]])printf("Truth\n");
                    else printf("Lie\n");
                }
                else if(x[i] < 0 )
                {
                    if(vis[-x[i]])printf("Lie\n");
                    else printf("Truth\n");
                }
           }
        }
        else
        {
            for(int i = 1;i <= n;i++)
            {
                int y = x[i];
                if(y > 0)
                {
                    if(vis[y])p[i] = 2;
                    else p[i] = 3;
                }
                if(y < 0)
                {
                    if(vis[-y])p[i] = 2;
                    else p[i]=1;
                }
            }
            for(int i = 1;i <= n;i++)
            {
                if(p[i] == 1)printf("Truth\n");
                else if(p[i] == 2)printf("Not defined\n");
                else if(p[i] == 3)printf("Lie\n");
            }
        }
    }
    return 0;
}

FZU 2203
Problem 2203 单纵大法好
Accept: 79 Submit: 188
Time Limit: 5000 mSec Memory Limit : 65536 KB
Problem Description

人在做,天在看,单纵不怂保平安

众娘皆为轮回来,敢教POI进夜战。

勿怪战列低智商,航母不是一个样?

假摔不虚有损管,大破进击是真相!

老S最近喜欢上某个搜集战舰的游戏,这个游戏中很重要的一个内容是能编排自己的战舰,通过出击完成任务来获取资源或新的战舰。大家都说老S是一个“直男”,所以他喜欢把战舰排成一条直线。目前老S正准备完成某个新的任务--“困难级丹麦海峡”,可以将地图视为1*N的一列方格(下标为1,2,...,N),老S有K列战舰,每列战舰长度为A。老S可以将自己的战舰布局在地图中的任意位置,但是两列战舰之间至少要有一个空格子,并且显然战舰是不能重叠放置的。老S通过内部人员率先知道了敌军的炮弹将会打向那些位置,老S希望使自己的舰队尽量晚的被第一次击中。请输出老S的舰队最晚将被敌方炮弹第一次击中?如果老S的舰队可以不被敌方炮弹击中则输出-1。
Input

包含多组数据

每组数据第一行有3个整数分别为N,K,A 分别表示地图长度,老S拥有的战舰数,每艘战舰的长度。(1<=N,K,A<=200000)

第二行有1个整数M,表示敌方炮弹数。 (1<=M<=N)

第三行有M个整数,Xi表示第i个敌方炮弹将击中位置Xi (1<=Xi<=N)击中位置Xi (1<=Xi<=N)
Output

仅有一个整数ANS,表示老S最晚将被哪个炮弹第一次击中
Sample Input
5 1 3
2
1 5
5 1 3
1
3
Sample Output
-1
1
解题思路:因为炮弹的轰炸时间顺序是递增的,并且时间越往后,能放置船只的位置就越少。
所以可以二分时间找满足条件的时间,如果对于某个时间t,如果t-1时间后能放置所以船只免受轰击
而t时间后不能放置所以船只免受轰击即找到了满足条件的t。
注意:每个船只直接要有至少一个单位间隔。
AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 200000 + 10;
int store[maxn],bomb[maxn];
int n,num,len,m;
bool check(int x)  //放置到x为止炸弹,看是否能够容纳多少船
{
    for(int i = 1;i <= x;i++)
        bomb[i] = store[i];
    sort(bomb + 1,bomb + x + 1);//排序
    bomb[0] = 0;
    bomb[x + 1] = n + 1;
    int cnt = 0;
    for(int i = 0;i <= x;i++)
    {
        cnt += (bomb[i + 1] - bomb[i]) / (len + 1);//这m个炮弹把n个空格分成了t段连续的空位,对于每一段长度为g的空位,设能放x艘船, 应满足:A*x + (x-1) <= g, 得: x = (g+1) / (A+1)
    }
    if(cnt >= num)//如果可放置船只数大于实际船只数,返回true
        return true;
    else
        return false;
}
int main()
{
    while(scanf("%d%d%d",&n,&num,&len) != EOF)
    {
        scanf("%d",&m);
        for(int i = 1;i <= m;i++)
            scanf("%d",&store[i]);
        int low = 1,high = m,ans = 0;
        while(low <= high)//二分炸弹
        {
            int mid = (low + high) / 2;
            if(check(mid))
            {
                ans = mid;
                low = mid + 1;
            }
            else
                high = mid - 1;
        }
        if(check(m))
            printf("-1\n");
        else
            printf("%d\n",ans + 1);
    }
    return 0;
}



你可能感兴趣的:(第一次比赛(续))