您的位置:首页 > 理论基础 > 计算机网络

2017年西南民族大学程序设计竞赛-网络同步赛

2017-12-30 17:47 309 查看
时间限制: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
<<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 = ab % mo

 先讨论无需取模的

  当b为偶数时:ab=a(b/2)*2=(a2)b/2

  当b为奇数时:ab=a*ab-1=a*(a2)(b-1)/2

  如   28=(22)4         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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ACM 牛客
相关文章推荐