1. 程式人生 > >2017年西南民族大學程式設計競賽-網路同步賽

2017年西南民族大學程式設計競賽-網路同步賽

時間限制:C/C++ 1秒,其他語言2秒
空間限制:C/C++ 131072K,其他語言262144K
64bit IO Format: %lld

題目描述

現在有一個N*M的矩形星圖。其中包括恆星和黑洞。恆星可以向上、下、左、右發射光束,且允許光束從其中穿過;黑洞會吸收所有經過的光束。 若一顆恆星向上、下、左、右發射光束,你能告訴我,該光束能否避免被黑洞吸收,進入星圖之外的區域麼?

輸入描述:

單組輸入。第一行三個正整數N,M,Q(1 <= N,M
<= 1000,1 <= Q <= 1000000),分別表示矩陣的行列,以及詢問的個數,詢問之間相互獨立。
然後一個N*M的矩陣,由’*’和’#’構成,表示星圖。’*’表示恆星,’#’表示黑洞。
最後Q行,表示Q個詢問,每行兩個正整數x,y(1 <= x <= N, 1 <= y
<= M)表示發光恆星的位置(從上往下數第x行,從左往右數第y列,且保證該位置一定是恆星)和一個字元p(p∈{‘L’, ‘R’,
‘D’, ‘U’},’R’表示向右;’L’表示向左;’D’表示向下’;’U’表示向上)表示該恆星產生光束的方向。

輸出描述:

一共Q行。對於每個詢問,若該恆星發出的光束能夠進入星圖之外的區域則輸出“YES”;否則輸出“NO”。(不包含引號)
示例1

輸入

4 5 5
**##*
*****
*#*#*
##**#
2 3 D
2 3 U
1 5 R
4 4 U
3 1 U

輸出

YES
NO
YES
NO
YES

思路:

一開始想的是暴力,但是看了看資料,還是放棄了。其實就是進行一個預處理即可,將四個方向轉換成不同的數字,分別判斷,例如一個點左邊無黑洞,那麼這個點左邊的點都可以將光射出,所以就不需要再計算一遍了,直接記錄就行。注意當向右遍歷時,其實只要不遇見‘#’,那麼從當前點向左就是相通的

程式碼:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <map>
#define maxn 1005
using namespace std;
int a[maxn][maxn][5];
int l,r,n,m,q;
char mp[maxn][maxn];
char ch[5];
bool flag;
map<char,int>s;
int main(){
    //ios::sync_with_stdio(false);
    s['L']=0;
    s['R']=1;
    s['D']=2;
    s['U']=3;
        scanf("%d%d%d",&n,&m,&q);
        for(int i=0;i<n;i++)
            scanf("%s",mp[i]);

        for(int i=0;i<n;i++){
            flag=false;
            for(int j=0;j<m;j++){
                if(flag==false&&mp[i][j]=='*'){
                    a[i][j][0]=1;
                }
                else {
                    a[i][j][0]=-1;
                    flag=true;
                }
            }
        }


        for(int i=0;i<n;i++){
            flag=false;
            for(int j=m-1;j>=0;j--){
                if(flag==false&&mp[i][j]=='*'){
                    a[i][j][1]=1;
                }
                else {
                    a[i][j][1]=-1;
                    flag=true;
                }
            }
        }

        for(int i=0;i<m;i++){
            flag=false;
            for(int j=n-1;j>=0;j--){
                if(flag==false&&mp[j][i]=='*') a[j][i][2]=1;
                else {
                    a[j][i][2]=-1;
                    flag=true;
                }
            }
        }

        for(int i=0;i<m;i++){
            flag=false;
            for(int j=0;j<n;j++){
                if(flag==false&&mp[j][i]=='*'){
                    a[j][i][3]=1;
                }
                else{
                    a[j][i][3]=-1;
                    flag=true;
                }
            }
        }

        while(q--){
            scanf("%d%d%s",&l,&r,ch);
            l--;
            r--;
            if(a[l][r][s[ch[0]]]==1) printf("YES\n");
            else printf("NO\n");

        }
        return 0;

}




時間限制:C/C++ 1秒,其他語言2秒
空間限制:C/C++ 32768K,其他語言65536K
64bit IO Format: %lld

題目描述

    XzzF最近過著吃土的日子,餓的神魂顛倒!突然看到有人在做美食節宣傳,有好多好吃的,但想吃到這些好吃的可以不容易!得答對主辦方出的題。     現在XzzF拿到這樣一道題:長度為N的01字串,且滿足以下條件的方案數有多少種?
        1、串中不能有兩個或多個連續的0。     例如,10、10101、11101是滿足條件的,而00、10001、10010是不滿足條件的。     XzzF已經餓的神志不清了!顯然沒有力氣回答這道題了,所以,你一定要幫XzzF吃上那些好吃的,不然就莫得了!

輸入描述:

一個整數N(1 <= N <= 20)。

輸出描述:

滿足題目所述條件的方案數。
示例1

輸入

1

輸出

2
示例2

輸入

2

輸出

3

說明

有01、10、11三種滿足條件的方案。

思路:遞推,多寫出幾種情況,便可以發現規律。dp[i]=dp[i-1]+dp][i-2];

程式碼:

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <vector>
#include <string>
#define ll long long
#define maxn 100005
#define mod 1000000007
int dp[25];
using namespace std;
int main(){
    ios::sync_with_stdio(false);
    int n;
    while(cin>>n){
        dp[1]=2;
        dp[0]=1;
        for(int i=2;i<=n;i++){
                dp[i]=dp[i-1]+dp[i-2];

        }
        cout<<dp[n]<<endl;
    }
    return 0;
};

時間限制:C/C++ 1秒,其他語言2秒
空間限制:C/C++ 262144K,其他語言524288K
64bit IO Format: %lld

題目描述

豬媽媽讓佩奇練習打字, 她給了佩奇一篇只有小寫字母的字串S ( 1 <= |S| <= 105)。 但是佩奇記不住鍵盤字母的位置,只能看著鍵盤一個一個打。淘氣的喬治趁佩奇不注意, 偷偷的換了鍵盤按鍵的位置。 喬治是這樣操作的:喬治每次扣下來兩個鍵帽, 並且將這兩個鍵帽互換位置重新安回去, 喬治越玩越起勁,一直重複了m(1 <= m <= 105)次。請輸出佩奇打完字後螢幕上顯示的實際字串。

輸入描述:

第一行輸入一個字串S ( 1 <= |S| <= 105);
第二行輸入一個數字m(1 <= m <= 105), 表示佩奇要操作m次。
之後有m行, 每行有兩個字母 c1, c2 表示佩奇要把這兩個鍵帽互換位置。

輸出描述:

輸出一行字串, 即佩奇用喬治玩壞的鍵盤輸出的實際字串。
示例1

輸入

helloworld
3
e o
h z
l p

輸出

zoppewerpd

備註:

|S| 是字串s長度

思路:

其實就是使用map,考慮到這一點就很簡單。一開始map初始化,mp[a]=a...,一開始用的是結構體,其實少考慮了兩次交換的情況。所以使用map,每次使兩個值進行交換即可

程式碼:

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <vector>
#include <string>
#include <map>
#define ll long long
#define maxn 100005
#define mod 1000000007
using namespace std;
char s[maxn];
map<char,char>mp;
char c1,c2;
int main(){
    ios::sync_with_stdio(false);
    int m;
    cin>>s;
    int len=strlen(s);
    for(int i=0;i<26;i++){
            mp['a'+i]='a'+i;
    }
    cin>>m;
    for(int i=1;i<=m;i++){
        cin>>c1>>c2;
        char ch;
        ch=mp[c1];
        mp[c1]=mp[c2];
        mp[c2]=ch;
    }
    for(int i=0;i<len;i++){
        cout<<mp[s[i]];

    }
    cout<<endl;
    return 0;
}
時間限制:C/C++ 1秒,其他語言2秒
空間限制:C/C++ 32768K,其他語言65536K
64bit IO Format: %lld

題目描述

一天小明同學拿著m種顏色的油漆去塗刷n塊格子,在塗刷的過程中他發現有很多種塗色方案,並很快的算出了答案,然後他發現如果塗好顏色的格子中只要存在某兩個相鄰的格子顏色一樣,他就會感到開心,他想知道有多少種讓他開心的塗刷方案。

輸入描述:

輸入僅包含一行,包含兩個數n,m分別表示格子數和顏色數。(1 <= n <= 1e12, 1 <= m <= 1e12)

輸出描述:

輸出一行包含一個整數,讓小明開心的塗刷方案數。 答案對1000000007取模
示例1

輸入

3 2

輸出

6

說明

一共有(1, 1, 2), (2, 1, 1), (2, 2, 1), (1, 2, 2), (1, 1, 1), (2, 2, 2) 這6種方案

思路:

想到運用快速冪這個問題就解決了,快速冪就是:

 已知底數a,指數b,取模值mo

  求ans = a% mo

先討論無需取模的

  當b為偶數時:ab=a(b/2)*2=(a2)b/2

  當b為奇數時:ab=a*ab-1=a*(a2)(b-1)/2

  如   28=(224         27=2*(22)3

  所以,我們可以如此迭代下去

  210=(22)5=(22)*[(22)2]2

   ①       ②              ③

  指數為10 是一個偶數,則底數2平方,指數變為一半 [ ①→② ]

  指數為5 是一個奇數,則先將底數提出作為係數(22),此時指數為4 是一個偶數,則底數22再平方,指數再變為一半 [ ②→③ ]

  歸納總結得到:

        當指數大於1時,若為 偶數 則將指數除以2,底數平方

                                   若為 奇數 則先提出一個為底數的係數(可直接把該係數乘進ans中),所以指數減1,然後再按照 偶數 的辦法做

不斷迭代下去,當指數為1時,則直接得出答案

  最後只要將每次相乘時取模即可,時間複雜度O(log2b)

快速冪程式碼:
inline int mi(int a,int b)
{
    int ans=1;
    a%=mo;
    while (b)
    {
        if (b&1) ans=ans*a%mo;
        b>>=1;
        a=a*a%mo;
    }
    return ans;
}

其實總共有m的n次方個方法減去不合格的也就是m*m-1*m-1*...所以就是m-1的n-1次方再乘以m,兩者相減就可以。注意判斷正負數

程式碼:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <map>
#define maxn 1005
#define mod 1000000007
#define ll long long
using namespace std;
ll mi(ll a,ll b,ll mo){
    ll ans=1;
    a%=mo;
    while(b){
        if(b&1) ans=ans*a%mo;
        b>>=1;
        a=a*a%mo;
    }
    return ans;
}
int main(){
    ios::sync_with_stdio(false);
    ll n,m,ans1,ans2,ans3,ans4,ans;
    while(cin>>n>>m){
        ans1=mi(m,n,mod);
        ans2=mi(m-1,n-1,mod);
        ans3=m%mod;
        ans4=ans3*ans2%mod;

        if(ans1-ans4>0){
            ans=(ans1-ans4)%mod;
            cout<<ans<<endl;
        }
        else {
            ans=(ans1-ans4+mod)%mod;
            cout<<ans<<endl;
        }
    }
 return 0;
}


時間限制:C/C++ 1秒,其他語言2秒
空間限制:C/C++ 131072K,其他語言262144K
64bit IO Format: %lld

題目描述

自從ZZZZone吃完糖果後,他開始改吃巧克力了,他每天想吃n個巧克力增在甜蜜值,他決定早上吃K個巧克力,晚上吃n - K個巧克力,每個巧克力在早上吃和在晚上吃的甜蜜值是不一樣的,他想讓自己得到的甜蜜值最大,並想知道最大是多少。 請你程式設計幫助他。

輸入描述:

第一行包含兩個數n,K表示每天要吃的巧克力數量和要在早上吃的數量。(n <= 100000, K <= n)
第二行包含n個整數Ai(1 <= i <= n) 表示個第i個巧克力在早上吃可得到的甜蜜值 (Ai <= 100000)
第三行包含n個整數Bi(1 <= i <= n) 表示個第i個巧克力在晚上吃可得到的甜蜜值 (Bi <= 100000)

輸出描述:

輸出僅一行包含一個整數表示ZZZZone能獲得的最大甜蜜值。
示例1

輸入

2 1
3 6
2 8

輸出

11

說明

早上吃第一個巧克力得到3甜蜜值,晚上吃第2個巧克力得到8的甜蜜值,所以最大可得到11的甜蜜值。

思路:

其實就是對早上和晚上的甜蜜值差進行排序即可。

程式碼:

#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int maxn=100000+10;
struct candy{
   LL a,b,c;
   bool operator <(const candy &aa)const{
        return (a-b)>(aa.a-aa.b);
   }
}can[maxn];
int main(){
    int n,k;
    scanf("%d%d",&n,&k);
    for(int i=0;i<n;i++){
        scanf("%lld",&can[i].a);
    }
    for(int i=0;i<n;i++){
        scanf("%lld",&can[i].b);
        can[i].c=can[i].a-can[i].b;
    }
    sort(can,can+n);

    for(int i=0;i<n;i++)
        cout<<can[i].c<<endl;

    LL all=0;
    for(int i=0;i<k;i++){
        all+=can[i].a;
    }
    for(int i=k;i<n;i++){
        all+=can[i].b;
    }
    printf("%lld\n",all);

    return 0;
}