1. 程式人生 > >2016 icpc北京區域賽重現賽---題解

2016 icpc北京區域賽重現賽---題解

題意:

 Weiming Lake, also named “Un-named Lake”, is the most famous scenic spot in Peking University. It is located in the north of the campus and is surrounded by walking paths, small gardens, and old red buildings with typical Chinese curly roofs. The lake was once the royal garden in Qing Dynasty. Boya tower stands on a little hill beside the lake. The lake and the tower form a distinctive landscape and a symbol of Peking University. Weiming Lake is a very good place for studying, reading, skating in the winter, and of course, jogging. More and more students and teachers run or walk around Weiming Lake every day and show how many paces they have covered in the mobile app WeChat Sports to get ”Zans” (applauses). ACMer X also enjoys jogging around Weiming Lake. His watch can measure and record an altitude value every meter. After a round of running, X collected the altitude data around the lake. Now he wants to find out the longest slope around the lake.

Input

There are no more than 20 test cases. Each case has two lines. The first line is an integer N (2 ≤ N ≤ 100) meaning that the length of the road around the lake is N meters. The second line contains N integers a1, a2 . . . aN , (0 ≤ a1, a2 . . . aN ≤ 100) indicating N altitude sample values around the lake. The samples are given in clockwise order, and the distance between two adjacent samples is one meter. Of course the distance between a1 and aN is also one meter. The input ends by a line of ‘0’.

Output

For each test case, print the length of the longest slope in meters. A slope is a part of the road around the lake, and it must keep going up or going down. If there are no slope, print ‘0’.

程式碼:

#include <bits/stdc++.h>
using namespace std;
const int MAXN=2*105;

int N,a[MAXN];

int main()
{
    a[0]=-1;
    while(scanf("%d",&N)!=EOF)
    {
        if(N==0) break;
        for(int i=1;i<=N;i++)
        {
            scanf("%d",&a[i]);
            a[i+N]=a[i];
        }
        bool flag=false;
        for(int i=2;i<=N;i++)
        {
            if(a[i]!=a[i-1]) flag=true;
        }
        if(flag==false)
        {
            printf("0\n");continue;
        }
        int uplen=0,downlen=0;
        int upans=0,downans=0;
        for(int i=2;i<=2*N;i++)
        {
            if(a[i]>a[i-1])
            {
                uplen++;
                upans=max(upans,uplen);
                downlen=0;
            }
            else if(a[i]<a[i-1])
            {
                downlen++;
                downans=max(downans,downlen);
                uplen=0;
            }
            else
            {
                uplen=0;downlen=0;
            }
        }
        printf("%d\n",max(upans,downans));
    }
    return 0;
}

 題意:

In country Light Tower, a presidential election is going on. There are two candidates, Mr. X1 and Mr. X2, and both of them are not like good persons. One is called a liar and the other is called a maniac. They tear(Chinese English word, means defame) each other on TV face to face, on newspaper, on internet . . . on all kinds of media. The country is tore into two parts because the people who support X1 are almost as many as the people who support X2. After the election day, X1 and X2 get almost the same number of votes. No one gets enough votes to win. According to the law of the country, the Great Judge must decide who will be the president. But the judge doesn’t want to offend half population of the country, so he randomly chooses a 6 years old kid Tom and authorize him to pick the president. Sounds weird? But the democracy in Light Tower is just like that. The poor or lucky little kid Tom doesn’t understand what is happening to his country. But he has his way to do his job. Tom’s ao shu(Chinese English word, means some kind of weird math for kids) teacher just left him a puzzle a few days ago, Tom decide that he who solve that puzzle in a better way will be president. The ao shu teacher’s puzzle is like this: Given a string which consists of five digits(‘0’..‘9’), like “02943”, you should change “12345” into it by as few as possible operations. There are 3 kinds of operations: 1. Swap two adjacent digits. 2. Increase a digit by one. If the result exceed 9, change it to it modulo 10. 3. Double a digit. If the result exceed 9, change it to it modulo 10. You can use operation 2 at most three times, and use operation 3 at most twice. As a melon eater (Chinese English again, means bystander), which candidate do you support? Please help him solve the puzzle.

Input

There are no more than 100,000 test cases. Each test case is a string which consists of 5 digits.

Output

For each case, print the minimum number of operations must be used to change “12345” into the given string. If there is no solution, print ‘-1’.

思路:

做的時候一直TLE。。主要是T太大了,,,

轉換了很多種方法,最後已經完全轉暈了,,,做不動了,,最後也沒能A,,賽後看看,大佬們bfs+預處理好了就ok了,,

程式碼:


#include <iostream>

#include <stdio.h>

#include <algorithm>

#include <cmath>

#include <math.h>

#include <cstring>

#include <string>

#include <queue>

#include <stack>

#include <stdlib.h>

#include <list>

#include <map>

#include <set>

#include <bitset>

#include <vector>

#define mem(a,b) memset(a,b,sizeof(a))

#define findx(x) lower_bound(b+1,b+1+bn,x)-b

#define FIN      freopen("input.txt","r",stdin)

#define FOUT     freopen("output.txt", What a Ridiculous Election"w",stdout)

#define S1(n)    scanf("%d",&n)

#define SL1(n)   scanf("%I64d",&n)

#define S2(n,m)  scanf("%d%d",&n,&m)

#define SL2(n,m)  scanf("%I64d%I64d",&n,&m)

#define Pr(n)     printf("%d\n",n)

#define lson rt << 1, l, mid

#define rson rt << 1|1, mid + 1, r

 

using namespace std;

typedef long long ll;

const double PI=acos(-1);

const int INF=0x3f3f3f3f;

const double esp=1e-6;

const int maxn=1e5+5;

 

const int MOD=1000000007;

const int mod=1e9+7;

int dir[5][2]={0,1,0,-1,1,0,-1,0};

 

int ans[maxn][5][5];//次數

struct node{

    int num[10];

    int op2,op3;

    int step;

};

int Q_sum(node A)

{

    int sum=0;

    for(int i=1;i<=5;i++)

    {

        sum+=A.num[i];

        sum*=10;

    }

    return sum/10;

}

void bfs(node t)

{

    queue<node> Q;

    mem(ans,INF);

    t.op2=3;//  +1

    t.op3=2;//  *2

    t.step=0;

    Q.push(t);

    int n=Q_sum(t);

    ans[n][t.op2][t.op3]=0;

    while(!Q.empty())

    {

        node u=Q.front();

        Q.pop();

 

        for(int i=2;i<=5;i++)//swap

        {

            node tu=u;

            swap(tu.num[i],tu.num[i-1]);

            int  num=Q_sum(tu);

            tu.step++;

            if(tu.step>=ans[num][tu.op2][tu.op3])

                continue;

            Q.push(tu);

            ans[num][tu.op2][tu.op3]=tu.step;

        }

        if(u.op2>0)//+1

        {

            for(int i=1;i<=5;i++)

            {

                node tu=u;

                tu.op2--;

                tu.num[i]=(tu.num[i]+1)%10;

                int num=Q_sum(tu);

                tu.step++;

                if(tu.step>=ans[num][tu.op2][tu.op3])

                    continue;

                Q.push(tu);

                ans[num][tu.op2][tu.op3]=tu.step;

            }

        }

        if(u.op3>0)//*2

        {

            for(int i=1;i<=5;i++)

            {

                node tu=u;

                tu.op3--;

                tu.num[i]=(tu.num[i]*2)%10;

                int num=Q_sum(tu);

                tu.step++;

                if(tu.step>=ans[num][tu.op2][tu.op3])

                    continue;

                Q.push(tu);

                ans[num][tu.op2][tu.op3]=tu.step;

            }

        }

    }

}

int main()

{

    node temp;

    for(int i=1;i<=5;i++)

        temp.num[i]=i;

    bfs(temp);

    char str[12];

    while(~scanf("%s",str+1))

    {

        node b;

        for(int i=1;i<=5;i++)

            b.num[i]=str[i]-'0';

        int n=Q_sum(b);

        int res=INF;

        for(int i=0;i<=3;i++)

            for(int j=0;j<=2;j++)

        {

            res=min(res,ans[n][i][j]);

        }

 

        if(res==INF)

            printf("-1\n");

        else

            printf("%d\n",res);

    }

    return 0;

}

 題意:

Peking University Student Folk Music Band has a history of more than 90 years. They play Chinese traditional music by Chinese traditional instruments, such as Pipa, Erhu and Guzheng, etc. Doctor Li is a member of that band, and also a former ACMer. Now he is doing some research on Chinese ancient music. Many Chinese ancient music has only five kinds of tones, which can be denoted by ‘C’,‘D’,‘E’,‘G’, and ‘A’. Given a piece of music score, Li wants to do some simple statistics.

Input

There are no more than 20 test cases. In each test case: The first line contains two integers n and m (2 ≤ n, m ≤ 20), indicating that a piece of music score is represented by an n × m matrix of tones. Only ‘C’,‘D’,‘E’,‘G’, and ‘A’ can appear in the matrix. Then the n × m matrix follows. The input ends with a line of ‘0 0’.

Output

For each test case: For each kind of tone shown in the matrix, calculate the appearing times of it, and print the result in descending order according to the appearing times. If more than one kind of tones has the same appearing times, print them in the lexicographical order.

思路:就是n*m的字元矩陣中,每個字元的數量,數量為0的不輸出,其他的按題目要求排個序就可以

程式碼:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,m;
struct AA
{
    char ch;
    int num;
    bool operator<(const AA&aa)const
    {
        if(num==aa.num) return ch<aa.ch;
        return num>aa.num;
    }
}pos[30];
int T;
int main()
{
    char ch[30];
    while(~scanf("%d%d",&n,&m))
    {
        if(n==0&&m==0) break;
        for(int i=0;i<26;i++)
        {
            pos[i].ch='A'+i;
            pos[i].num=0;
        }

        for(int i=1;i<=n;i++)
        {
            scanf("%s",ch);

            for(int j=0;j<m;j++)
            {
                pos[ch[j]-'A'].num++;
            }
        }
        sort(pos,pos+26);
        for(int i=0;i<=25;i++)
        {
            if(pos[i].num==0) break;
            if(pos[i+1].num!=0)
            cout<<pos[i].ch<<" "<<pos[i].num<<" ";
            else
            {
                cout<<pos[i].ch<<" "<<pos[i].num<<endl;
            }
        }
    }


}

題意:

Driver Ji likes the digit “1”. He has an accumulator which shows the sum of input number. He lists all of positive number no more than N and starts counting from one, two, three . . . Every time he counts a number he will add the number of digit “1” in this number to accumulator at the same time. The amazing thing happens! At some times, when he finishes counting a number X, the number which on the accumulator is X exactly, he will regard X as “JiLi Number” which means lucky number. Now he wants to know the number of “JiLi Numbers” and the biggest “JiLi Number” no more than N.

Input

There are several test cases and the each test case is a line contains an positive integer N, (1 < N ≤ 10100)

Output

For each test case, output two integers which donates the number of “JiLi Numbers” and the biggest “JiLi Number”.

思路:

暴力打個表,83以後就不輸出了,猜了一下一共83個,真是良心樣例!

程式碼:

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;

ll num[83]={1,199981,199982,199983,199984,199985,199986,199987,199988,199989,199990,200000,200001,1599981,1599982,1599983,1599984,1599985,1599986,1599987,1599988,1599989,1599990,2600000,2600001,13199998,35000000,35000001,35199981,35199982,35199983,35199984,35199985,35199986,35199987,35199988,35199989,35199990,35200000,35200001,117463825,500000000,500000001,500199981,500199982,500199983,500199984,500199985,500199986,500199987,500199988,500199989,500199990,500200000,500200001,501599981,501599982,501599983,501599984,501599985,501599986,501599987,501599988,501599989,501599990,502600000,502600001,513199998,535000000,535000001,535199981,535199982,535199983,535199984,535199985,535199986,535199987,535199988,535199989,535199990,535200000,535200001,1111111110};
string s;

int main()
{
    num[83]=100000000000;
    while(cin>>s)
    {
        if(s.length()>11)
            cout<<83<<" "<<1111111110<<endl;
        ll n=0;
        //for(int i=s.length()-1;i>=0;i--)
            //n+=s[i]*pow(10,i);
        for(int i=0;i<=s.length()-1;i++)
        {
            n=n*10+s[i]-'0';
        }
        //cout<<n<<endl;
        for(int i=0;i<=82;i++)
        {
            if(n>=num[i]&&num[i+1]>n)
            {
                cout<<(i+1)<<" "<<num[i]<<endl;
                break;
            }
        }
    }
    return 0;
}