【紀中2020.5.2日】模擬賽題解

目錄:

T1:笨小猴
T2:數列
T3:Jam的計數法
T4:傳紙條

這次的題一些洛谷上有 一些沒有 總之不是USACO的題了……

正題:

T1:笨小猴

題目描述

笨小猴的詞彙量很小,所以每次做英語選擇題的時候都很頭疼。但是他找到了一種方法,經試驗證明,用這種方法去選擇選項的時候選對的機率非常大!
這種方法的具體描述如下:假設maxn是單詞中出現次數最多的字母的出現次數,minn是單詞中出現次數最少的字母的出現次數,如果maxn-minn是一個質數,那麼笨小猴就認爲這是個Lucky Word,這樣的單詞很可能就是正確的答案。

輸入

輸入文件word.in只有一行,是一個單詞,其中只可能出現小寫字母,並且長度小於100。

輸出

輸出文件word.out共兩行,第一行是一個字符串,假設輸入的的單詞是Lucky Word,那麼輸出“Lucky Word”,否則輸出“No Answer”;
第二行是一個整數,如果輸入單詞是Lucky Word,輸出maxn-minn的值,否則輸出0。

樣例輸入

【輸入樣例1】

error

【輸入樣例2】

olympic

樣例輸出

【輸出樣例1】

Lucky Word
2

【輸出樣例1解釋】

單詞error中出現最多的字母r出現了3次,出現次數最少的字母出現了1次,3-1=22是質數。

【輸出樣例2】

No Answer
0

【輸出樣例2解釋】

單詞olympic中出現最多的字母出現了1次,出現次數最少的字母出現了1次,1-1=00不是質數。

分析:

此題可用一點小打表
打表找出100以內的質數 再分別找出
出現次數最多的字母
出現次數最少的字母
將他們相減 得到一個
最後拿去匹配 輸出

CODE:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int a[27];
int main(){
	freopen("word.in","r",stdin);
	freopen("word.out","w",stdout);
    int len=0,x=0,maxn=-9999,minn=9999;
    string s;
    cin>>s;
    len=s.size();
    for(int i=0;i<=len-1;i++){
        x=s[i];
        a[x-97]++;  //記錄每個字母出現次數
    }
    const int prime[25]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97};
    //100以內的質數表
    for(int i=0;i<26;i++){
        if(a[i]<minn&&a[i]!=0)minn=a[i];  //最少
    }
    for(int i=0;i<26;i++){
        if(a[i]>maxn)maxn=a[i];  //最大
    }
    int sub=maxn-minn;  //差
    for(int i=0;i<=24;i++){
        if(sub==prime[i]){  //匹配了
            cout<<"Lucky Word"<<endl;
            cout<<sub;
            return 0;
        }
    }
    cout<<"No Answer"<<endl<<"0";
    return 0;
} 

T2:數列

題目描述

給定一個正整數k(3≤k≤15),把所有k的方冪及所有有限個互不相等的k的方冪之和構成一個遞增的序列,例如,當k=3時,這個序列是:
1,3,4,9,10,12,13,…
(該序列實際上就是:30,31,30+31,32,30+32,31+32,30+31+32,…)
請你求出這個序列的第N項的值(用10進制數表示)。
例如,對於k=3,N=100,正確答案應該是981。

輸入

輸入文件sequence.in 只有1行,爲2個正整數,用一個空格隔開:
k N(k、N的含義與上述的問題描述一致,且3≤k≤15,10≤N≤1000)。

輸出

輸出文件sequence.out 爲計算結果,是一個正整數(在所有的測試數據中,結果均不超過2.1*10^9)。(整數前不要有空格和其他符號)。

樣例輸入

3 100

樣例輸出

981

分析:

這道題可進制轉換
也可以做搜索 DFS
看註釋去

CODE:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
long long a,k,x[501],y[1101],poww=1,can=0;
void dfs(long long poww,long long l)
{
    if(poww==11)
    {
		return;
    } 
	else{ 		
	int cat=0;
        for(int i=1;i<=can;i++)
        {
            if(l==y[i])  //判斷重複值
            {
                cat++;
                break;
            }
        }
        if(cat==0)  //莫得加入數組
        {
            can++;
           	y[can]=l;
        }
    	dfs(poww+1,l+x[poww]);
    	dfs(poww+1,l);  //加或不加
	}
}
int main()
{
	freopen("sequence.in","r",stdin);
	freopen("sequence.out","w",stdout);
    cin>>a>>k;
    x[0]=1;
    for(int i=1;i<=10;i++)
    {
        x[i]=poww*a;
        poww=a*poww;
    }//用x數組表示a的poww次方數;
   //因爲題目中的範圍小於等於1000;
   //故到10就行了;
    dfs(0,0);
    sort(y+1,y+can+1);
    cout<<y[k+1];  //數組第一個值爲0
    return 0;
}

T3:Jam的計數法

題目描述

Jam是個喜歡標新立異的科學怪人。他不使用阿拉伯數字計數,而是使用小寫英文字母計數,他覺得這樣做,會使世界更加豐富多彩。在他的計數法中,每個數字的位數都是相同的(使用相同個數的字母),英文字母按原先的順序,排在前面的字母小於排在它後面的字母。我們把這樣的“數字”稱爲Jam數字。
在Jam數字中,每個字母互不相同,而且從左到右是嚴格遞增的。每次,Jam還指定使用字母的範圍,例如,從2到10,表示只能使用{b,c,d,e,f,g,h,i,j}這些字母。如果再規定位數爲5,那麼,緊接在Jam數字“bdfij”之後的數字應該是“bdghi”。(如果我們用U、V依次表示Jam數字“bdfij”與“bdghi”,則U<V,且不存在Jam數字P,使U<P<V)。你的任務是:對於從文件讀入的一個Jam數字,按順序輸出緊接在後面的5個Jam數字,如果後面沒有那麼多Jam數字,那麼有幾個就輸出幾個。

輸入

輸入文件count.in 有2行:
第1行爲3個正整數,用一個空格隔開:s t w(其中s爲所使用的最小的字母的序號,t爲所使用的最大的字母的序號。w爲數字的位數,這3個數滿足:1≤s≤26, 2≤w≤t-s )
第2行爲具有w個小寫字母的字符串,爲一個符合要求的Jam數字。 所給的數據都是正確的,不必驗證。

輸出

輸出文件count.out 最多爲5行,爲緊接在輸入的Jam數字後面的5個Jam數字,如果後面沒有那麼多Jam數字,那麼有幾個就輸出幾個。每行只輸出一個Jam數字,是由w個小寫字母組成的字符串,不要有多餘的空格。

樣例輸入

2 10 5
bdfij

樣例輸出

bdghi
bdghj
bdgij
bdhij
befgh

分析:

dfs 需要注意如何退出
後面就是普通dfs
退出部分則是:
不斷地匹配 標記 停止循環 等等等等……
詳見註釋

CODE:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,flag,ans,s,t;
char a[17],an[17];
char b[27]={'*','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};  //字符表
int vis[27];
void dfs(int cur){  //dfs
	if(cur==n+1){
		int f2=0,f=0;
		for(int i=1;i<=n;i++) if(a[i]!=an[i]) f=1;  //不相同先標記 
		if(f==0) return;
		for(int i=1;i<=n;i++){
			if(an[i]>a[i]){
				break;  //判斷大小 
			}
			else if(an[i]<a[i]){  //下一種情況 標記
				f2=1;
				break;
			}
		}
		if(f2==1) return;
		flag++;  //做完一位上的字符
		for(int i=1;i<n;i++) cout<<an[i];  //輸出即可
		cout<<an[n]<<endl;
		if(flag==5) exit(0);  //共5位
 
	}else{
		for(int i=s;i<=t;i++){ 
			if(vis[i]==0&&b[i]>an[cur-1]){  //深搜 下一個數
				an[cur]=b[i];
				vis[i]=1;
				dfs(cur+1);
				vis[i]=0;
			}
		}
	}
}
int main() {
	freopen("count.in","r",stdin);
	freopen("count.out","w",stdout);
	scanf("%d%d%d",&s,&t,&n);
	for(int i=1;i<=n;i++) cin>>a[i];  //讀入
	dfs(1);
	return 0;
}

T4:傳紙條

題目描述

小淵和小軒是好朋友也是同班同學,他們在一起總有談不完的話題。一次素質拓展活動中,班上同學安排做成一個m行n列的矩陣,而小淵和小軒被安排在矩陣對角線的兩端,因此,他們就無法直接交談了。幸運的是,他們可以通過傳紙條來進行交流。紙條要經由許多同學傳到對方手裏,小淵坐在矩陣的左上角,座標(1,1),小軒坐在矩陣的右下角,座標(m,n)。從小淵傳到小軒的紙條只可以向下或者向右傳遞,從小軒傳給小淵的紙條只可以向上或者向左傳遞。

在活動進行中,小淵希望給小軒傳遞一張紙條,同時希望小軒給他回覆。班裏每個同學都可以幫他們傳遞,但只會幫他們一次,也就是說如果此人在小淵遞給小軒紙條的時候幫忙,那麼在小軒遞給小淵的時候就不會再幫忙。反之亦然。

還有一件事情需要注意,全班每個同學願意幫忙的好感度有高有低(注意:小淵和小軒的好心程度沒有定義,輸入時用0表示),可以用一個0-100的自然數來表示,數越大表示越好心。小淵和小軒希望儘可能找好心程度高的同學來幫忙傳紙條,即找到來回兩條傳遞路徑,使得這兩條路徑上同學的好心程度只和最大。現在,請你幫助小淵和小軒找到這樣的兩條路徑。

輸入

輸入文件message.in的第一行有2個用空格隔開的整數m和n,表示班裏有m行n列(1<=m,n<=50)。

接下來的是一個m*n的矩陣,矩陣中第i行j列的整數表示坐在第i行j列的學生的好心程度。每行的n個整數之間用空格隔開。

輸出

輸出文件message.out共一行,包含一個整數,表示來回兩條路上參與傳遞紙條的學生的好心程度之和的最大值。

樣例輸入

3 3
0 3 9
2 8 5
5 7 0

樣例輸出

34

分析:

DP DP DP
本來想着用搜索淼過 結果被制裁
一邊傳紙條一邊判斷上下左右的大小
找到最大的就往那裏累加
然後繼續走 直到中點爲止
啊啊啊 三維數組的DP我人都傻了

CODE:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
int f[101][101][101];
int a[101][101];
int m,n,cnt;
int main()
{
	freopen("message.in","r",stdin);
	freopen("message.out","w",stdout);
    cin>>m>>n;
    for(int i=1;i<=m;i++)
    	for(int j=1;j<=n;j++)
        	cin>>a[i][j];
    memset(f,-1,sizeof(f)); 
    f[2][1][1]=0;  //初始化起點
    for(int k=3;k<m+n;k++)  //枚舉路徑
    	for(int i=1;i<n;i++)  //枚舉斜線
    		for(int j=i+1;j<=n;j++)
        	{
          		cnt=f[k][i][j];
          		cnt=max(f[k-1][i][j],cnt);  //上下左右
          		cnt=max(f[k-1][i-1][j],cnt);
          		cnt=max(f[k-1][i][j-1],cnt);
          		cnt=max(f[k-1][i-1][j-1],cnt);
          		if(cnt==-1) continue;
          			f[k][i][j]=cnt+a[k-i][i]+a[k-j][j];  //加進去
        	}
    cout<<f[m+n-1][n-1][n];
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章