2016中國大學生程序設計競賽(ccpc 長春)題解報告

此文章可以使用目錄功能喲↑(點擊上方[+])

集訓隊呆了那麼長時間,還是隻會劃劃水...

鏈接→2016中國大學生程序設計競賽(長春)-重現賽

 Problem 1002 Fraction

Accept: 0    Submit: 0
Time Limit: 2000/1000 MS (Java/Others)    Memory Limit : 65536/65536 K (Java/Others)

 Problem Description

Mr. Frog recently studied how to add two fractions up, and he came up with an evil idea to trouble you by asking you to calculate the result of the formula below:


As a talent, can you figure out the answer correctly?

 Input

The first line contains only one integer T, which indicates the number of test cases.

For each test case, the first line contains only one integer n (n≤8).

The second line contains n integers: a1,a2,⋯an(1≤ai≤10).

The third line contains n integers: b1,b2,⋯,bn(1≤bi≤10).

 Output

For each case, print a line “Case #x: p q”, where x is the case number (starting from 1) and p/q indicates the answer.

You should promise that p/q is irreducible.

 Sample Input

1
2
1 1
2 3

 Sample Output

Case #1: 1 2

Hint

Here are the details for the first sample:
2/(1+3/1) = 1/2

 Problem Idea

解題思路:

【題意】
給你一個整數n

以及數組a1,a2,…,an

數組b1,b2,…,bn

要求求出


【類型】
簽到模擬題
【分析】
題目還是比較好理解的,就是求下面這個東西


因爲n最大才8,所以毫無疑問暴力的做法是最佳選擇

因此,我們只需從公式內部往外計算就可以了

另外由於最終答案會以分數形式輸出,所以過程中兩數還不能直接相除,分子和分母要分開計算

最初,分子x(0)爲bn,分母y(0)爲an

一輪計算後,分子x(1)爲,分母y(1)爲

顯然,k輪計算後,分子x(k)爲,分母y(k)爲

都是和前一輪結果相關的

所以還是靠循環搞定

【時間複雜度&&優化】
O(n)

題目鏈接→HDU 5912 Fraction

 Source Code

/*Sherlock and Watson and Adler*/
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<bitset>
#include<cmath>
#include<complex>
#include<string>
#include<algorithm>
#include<iostream>
#define eps 1e-9
#define LL long long
#define PI acos(-1.0)
#define bitnum(a) __builtin_popcount(a)
using namespace std;
const int N = 10;
const int M = 100005;
const int inf = 1000000007;
const int mod = 101;
int a[N],b[N];
int gcd(int a,int b)
{
    if(a%b)
        return gcd(b,a%b);
    return b;
}
int main()
{
    int t,n,i,x,y,z,k,p=1;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(i=1;i<=n;i++)
            scanf("%d",&a[i]);
        for(i=1;i<=n;i++)
            scanf("%d",&b[i]);
        y=a[n];x=b[n];
        for(i=n-1;i>0;i--)
        {
            z=y;
            y=y*a[i]+x;
            x=z*b[i];
        }
        k=gcd(x,y);
        printf("Case #%d: %d %d\n",p++,x/k,y/k);
    }
    return 0;
}

 Problem 1004 Triangle

Accept: 0    Submit: 0
Time Limit: 2000/1000 MS (Java/Others)    Memory Limit : 65536/65536 K (Java/Others)

 Problem Description

Mr. Frog has n sticks, whose lengths are 1,2, 3⋯n respectively. Wallice is a bad man, so he does not want Mr. Frog to form a triangle with three of the sticks here. He decides to steal some sticks! Output the minimal number of sticks he should steal so that Mr. Frog cannot form a triangle with
any three of the remaining sticks.

 Input

The first line contains only one integer T (T≤20), which indicates the number of test cases. 

For each test case, there is only one line describing the given integer n (1≤n≤20).

 Output

For each test case, output one line “Case #x: y”, where x is the case number (starting from 1), y is the minimal number of sticks Wallice should steal.

 Sample Input

3
4
5
6

 Sample Output

Case #1: 1
Case #2: 1
Case #3: 2

 Problem Idea

解題思路:

【題意】
長度爲1,2,3,…,n的n根木棒

問至少偷走幾根木棒,才能使得剩下的木棒任意三根都無法組成三角形

【類型】
打表
【分析】
我們都知道,三根木棒要構成三角形

需滿足三根木棒中任意兩根木棒長度之和大於剩下的那根木棒

對於1,2,3,…,n這n根木棒,爲了儘可能構不成三角形

顯然儘可能要留下長度小的

爲什麼呢?

假設三根木棒中較短的兩根木棒長度分別爲x,y,且y>x

那麼,最長的那根木棒長度只要<x+y(當然,長度肯定是>y的)就可以構成三角形

那麼,x和y的值越大,意味着最長的那根木棒可選擇性越大

這就需要去掉更多的木棒才能使得剩下的模板構不成三角形

故需要儘可能留下長度小的木棒

因此,對於1,2,3,…,20這些長度的木棒,顯然要留下的木棒爲1,2,3,5,8,13(斐波那契數列有木有^_^)

於是,照此打表輸出即可

【時間複雜度&&優化】
O(1)

題目鏈接→HDU 5914 Triangle

 Source Code

/*Sherlock and Watson and Adler*/
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<bitset>
#include<cmath>
#include<complex>
#include<string>
#include<algorithm>
#include<iostream>
#define eps 1e-9
#define LL long long
#define PI acos(-1.0)
#define bitnum(a) __builtin_popcount(a)
using namespace std;
const int N = 25;
const int M = 100005;
const int inf = 1000000007;
const int mod = 101;
int s[N]={0,0,0,0,1,1,2,3,3,4,5,6,7,7,8,9,10,11,12,13,14};
int main()
{
    int t,n,i,p=1;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        printf("Case #%d: %d\n",p++,s[n]);
    }
    return 0;
}

 Problem 1006 Harmonic Value Description

Accept: 0    Submit: 0
Time Limit: 2000/1000 MS (Java/Others)    Memory Limit : 65536/65536 K (Java/Others)

Special Judge

 Problem Description

The harmonic value of the permutation p1,p2,⋯pn is


Mr. Frog is wondering about the permutation whose harmonic value is the strictly k-th smallest among all the permutations of [n].

 Input

The first line contains only one integer T (1≤T≤100), which indicates the number of test cases.

For each test case, there is only one line describing the given integers n and k (1≤2k≤n≤10000).

 Output

For each test case, output one line “Case #x: p1 p2 ⋯ pn”, where x is the case number (starting from 1) and p1 p2 ⋯ pn is the answer.

 Sample Input

2
4 1
4 2

 Sample Output

Case #1: 4 1 3 2
Case #2: 2 4 1 3

 Problem Idea

解題思路:

【題意】
1~n的全排列中諧波值嚴格第k小的排列爲多少

排列p1,p2,…,pn的諧波值定義如下:


【類型】
構造
【分析】

此題關鍵是找突破口

在沒找到突破口前強行做還是有點難度的

由於p1,p2,…,pn是1~n全排列中的一種

可想而知的是,嚴格第1小的排列必定是那種任意相鄰兩個數最大公約數爲1的排列,例如排列1,2,3,…,n

此外,1~n這n個數還是很奇妙的,我們可以構造出任意約數爲k的對,當然,前提是k<=n/2

故嚴格第k小的排列可以是存在一對相鄰兩個數最大公約數爲k,其餘任意相鄰兩個數最大公約數爲1的排列

另外,題目已經做了方便我們構造的規定

即2k≤n

故最方便的構造方法是將2k和k提取出來放在排列最前面,然後構造相鄰兩數最大公約數爲1的排列

即下述這種排列:

2k,k,k-1,k-2,…,2,1,k+1,k+2,…,2k-1,2k+1,…,n-1,n

這麼做的原因如下:

⑴gcd(k,2k)=k

⑵自然數中相鄰兩數的最大公約數爲1

⑶自然數中相鄰兩奇數的最大公約數爲1,即gcd(2k-1,2k+1)=1

⑷1與任何數的最大公約數爲1

【時間複雜度&&優化】
O(n)

題目鏈接→HDU 5916 Harmonic Value Description

 Source Code

/*Sherlock and Watson and Adler*/
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<bitset>
#include<cmath>
#include<complex>
#include<string>
#include<algorithm>
#include<iostream>
#define eps 1e-9
#define LL long long
#define PI acos(-1.0)
#define bitnum(a) __builtin_popcount(a)
using namespace std;
const int N = 25;
const int M = 100005;
const int inf = 1000000007;
const int mod = 101;
int main()
{
    int t,n,k,i,p=1;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&k);
        printf("Case #%d:",p++);
        printf(" %d %d",2*k,k);
        for(i=k-1;i>=1;i--)
            printf(" %d",i);
        for(i=k+1;i<=n;i++)
            if(i!=2*k)
                printf(" %d",i);
        puts("");
    }
    return 0;
}

 Problem 1008 Sequence I

Accept: 0    Submit: 0
Time Limit: 3000/1500 MS (Java/Others)    Memory Limit : 65536/65536 K (Java/Others)

 Problem Description

Mr. Frog has two sequences a1,a2,⋯,an and b1,b2,⋯,bm and a number p. He wants to know the number of positions q such that sequence b1,b2,⋯,bm is exactly the sequence where q+(m−1)p≤n and q≥1.

 Input

The first line contains only one integer T≤100, which indicates the number of test cases.

Each test case contains three lines.

The first line contains three space-separated integers 1≤n≤10^6,1≤m≤10^6 and 1≤p≤10^6.

The second line contains n integers a1,a2,⋯,an(1≤ai≤10^9).

the third line contains m integers b1,b2,⋯,bm(1≤bi≤10^9).

 Output

For each test case, output one line “Case #x: y”, where x is the case number (starting from 1) and y is the number of valid q’s.

 Sample Input

2
6 3 1
1 2 3 1 2 3
1 2 3
6 3 2
1 3 2 2 3 1
1 2 3

 Sample Output

Case #1: 2
Case #2: 1

 Problem Idea

解題思路:

【題意】
已知序列A和序列B以及p

問有多少個位置q,使得b1,b2,…,bm與恰好匹配

【類型】
KMP
【分析】
其實本題只是在裸的KMP上做了稍微的修改罷了

裸的KMP是一一匹配,而本題要求的是隔p個匹配

因此,計算next數組部分是不需要修改的,只需要改一下匹配過程

當序列A中的a[i]等於序列B中的b[j]時,將原先的i++改爲i+=p即可

【時間複雜度&&優化】
O(N+M)

題目鏈接→HDU 5918 Sequence I

 Source Code

/*Sherlock and Watson and Adler*/
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<bitset>
#include<cmath>
#include<complex>
#include<string>
#include<algorithm>
#include<iostream>
#define eps 1e-9
#define LL long long
#define PI acos(-1.0)
#define bitnum(a) __builtin_popcount(a)
using namespace std;
const int N = 1000005;
const int M = 100005;
const int inf = 1000000007;
const int mod = 101;
int c[N],s[N],s2[N],n,m,p;
void getnext()
{
    int i=0,j=-1,l=m;
    c[0]=-1;
    while(i<l)
        if(j==-1||s2[i]==s2[j])
            c[++i]=++j;
        else
            j=c[j];
}
int kmp(int x)
{
    int i=x,j=0,k=0,len=n,l=m;
    while(i<len)
    {
        if(j==-1|s[i]==s2[j])
            i+=p,j++;
        else
            j=c[j];
        if(j==l)
            k++,j=c[j];
    }
    return k;
}
int main()
{
    int t,i,ans,k=1;
    scanf("%d",&t);
    while(t--)
    {
        ans=0;
        scanf("%d%d%d",&n,&m,&p);
        for(i=0;i<n;i++)
            scanf("%d",&s[i]);
        for(i=0;i<m;i++)
            scanf("%d",&s2[i]);
        getnext();
        for(i=0;i<p&&i<n;i++)
            ans+=kmp(i);
        printf("Case #%d: %d\n",k++,ans);
    }
    return 0;
}

 Problem 1010 Ugly Problem

Accept: 0    Submit: 0
Time Limit: 2000/1000 MS (Java/Others)    Memory Limit : 65536/65536 K (Java/Others)

Special Judge

 Problem Description

Everyone hates ugly problems.

You are given a positive integer. You must represent that number by sum of palindromic numbers.

A palindromic number is a positive integer such that if you write out that integer as a string in decimal without leading zeros, the string is an palindrome. For example, 1 is a palindromic number and 10 is not.

 Input

In the first line of input, there is an integer T denoting the number of test cases.

For each test case, there is only one line describing the given integer s (1≤s≤10^1000).

 Output

For each test case, output “Case #x:” on the first line where x is the number of that test case starting from 1. Then output the number of palindromic numbers you used, n, on one line. n must be no more than 50. en output n lines, each containing one of your palindromic numbers. Their sum must be exactly s.

 Sample Input

2
18
1000000000000

 Sample Output

Case #1:
2
9
9
Case #2:
2
999999999999
1

Hint

9 + 9 = 18
999999999999 + 1 = 1000000000000

 Problem Idea

解題思路:

【題意】
給你一個整數s,要求將它拆分成不超過50個迴文整數相加

輸出這些迴文整數

迴文整數的定義爲該整數存儲成字符串時,是迴文串

【類型】
大數+模擬
【分析】

每次將當前結果的前半段取出來,-1,構造成迴文串y,x-=y,直到x=0

特殊處理0~20的情況

具體看代碼,不懂提問

【時間複雜度&&優化】
O(n)

題目鏈接→HDU 5920 Ugly Problem

 Source Code

/*Sherlock and Watson and Adler*/
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<bitset>
#include<cmath>
#include<complex>
#include<string>
#include<algorithm>
#include<iostream>
#define eps 1e-9
#define LL long long
#define PI acos(-1.0)
#define bitnum(a) __builtin_popcount(a)
using namespace std;
const int N = 1005;
const int M = 55;
const int inf = 1000000007;
const int mod = 101;
char s[N];
int x[N],y[N],ans[M][N],u[2]={1,1};
void sub(int *a,int *b)//大數減法
{
    int i;
    for(i=1;i<=b[0];i++)
        a[i]-=b[i];
    for(i=1;i<=a[0];i++)
        if(a[i]<0)
            a[i]+=10,a[i+1]--;
    while(a[0]>1&&!a[a[0]])
        a[0]--;
}
int main()
{
    int t,i,j,n,k,p=1;
    scanf("%d",&t);
    while(t--)
    {
        k=0;
        scanf("%s",s);
        n=strlen(s);
        x[0]=n;//記錄當前位數
        for(i=0;s[i]!='\0';i++)
            x[n-i]=s[i]-'0';
        while(!(x[0]==1&&x[1]==0))
        {
            if(x[0]==1)//當前爲一位數
            {
                ans[k][0]=1;
                ans[k++][1]=x[1];
                break;
            }
            if(x[0]==2&&x[2]==1)//當前爲十位爲1的兩位數
            {
                if(x[1]==0)//10
                {
                    ans[k][0]=1;
                    ans[k++][1]=9;//9
                    ans[k][0]=1;//+
                    ans[k++][1]=1;//1
                    break;
                }
                if(x[1]==1)//11
                {
                    ans[k][0]=2;
                    ans[k][1]=1;
                    ans[k++][2]=1;//11
                    break;
                }
                ans[k][0]=2;
                ans[k][1]=1;
                ans[k++][2]=1;//11
                ans[k][0]=1;
                ans[k++][1]=x[1]-1;
                break;
            }
            for(i=x[0];i>x[0]/2;i--)
                y[i-x[0]/2]=x[i];
            y[0]=(x[0]+1)/2;//取出當前數的前一半
            sub(y,u);
            ans[k][0]=y[0]+y[0];
            if(ans[k][0]>x[0])
                ans[k][0]--;
            for(i=y[0],j=0;i;i--,j++)
                ans[k][ans[k][0]-j]=ans[k][y[0]-i+1]=y[i];//構造迴文串
            sub(x,ans[k++]);
        }
        printf("Case #%d:\n%d\n",p++,k);
        for(i=0;i<k;i++)
        {
            for(j=ans[i][0];j;j--)
                printf("%d",ans[i][j]);
            puts("");
        }
    }
    return 0;
}
菜鳥成長記
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章