A.计数问题
题目描述
试计算在区间1到n的所有整数中,数字x(0≤x≤9)共出现了多少次?例如,在1到11中,即在1、2、3、4、5、6、7、8、9、10、11中,数字1出现了4次。
输入
每组输入数据共1行,包含2个整数n、x,之间用一个空格隔开。
数据规模:
对于100%的数据,1≤n≤1000000,0≤x≤9。
输出
每组输出共1行,包含一个整数,表示x出现的次数。
样例输入
11 1
样例输出
4
思路:暴力,签到。
代码如下:
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string>
#include<set>
#include<math.h>
#include<map>
#include<string.h>
#include<stack>
#include<queue>
#define per(i,a,b) for(int i=a;i<=b;++i)
#define rep(i,a,b) for(int i=a;i>=b;--i)
#define inf 0x3f3f3f
using namespace std;
int main()
{
int n,x;
scanf("%d%d",&n,&x);
char s[8];
int p[10]={0};
per(i,1,n)
{
sprintf(s,"%d",i);
per(j,0,strlen(s)-1)
p[s[j]-'0']++;
}
printf("%d\n",p[x]);
return 0;
}
B.单词接龙
题目描述
单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如beast和astonish,如果接成一条龙则变为beastonish,另外相邻的两部分不能存在包含关系,例如at和atide间不能相连。
输入
每个测试文件只包含一组测试数据,每组输入的第一行为一个单独的整数n(n<=20)表示单词数,以下n行每行有一个单词,输入的最后一行为一个单个字符,表示“龙”开头的字母。你可以假定以此字母开头的“龙”一定存在。
输出
对于每组输入数据,输出以此字母开头的最长的“龙”的长度。
下面的测试样例最后连成的“龙”为atoucheatactactouchoose。
样例输入
5 at touch cheat choose tact a
样例输出
23
思路:预处理重复部分,因为数据小可使用搜索。赛后A,,,心累。
代码如下:
#include<iostream>
#include<cstring>
#define per(i,a,b) for(int i=a;i<=b;++i)
#define rep(i,a,b) for(int i=a;i>=b;--i)
using namespace std;
int n,p[22],vis[22],l,ans,mp[21][21];
string s[21];
int fun(string a,string b)
{
int w=min(a.length(),b.length());
per(i,1,w)
if(a.substr(a.length()-i,i)==b.substr(0,i))//判断后半段与前半段是否相等
return b.length()-i;//返回去重后的长度
return 0;
}
void dfs(int a,int c)//a为当前第几节躯干,c为长度
{
per(i,1,n)
{
if(mp[p[a]][i]!=0&&vis[i]<2)//可连接且使用次数小于2
{
p[a+1]=i;//指向上一节
l+=mp[p[a]][i];//加长度
vis[i]++;
ans=max(l,ans);
dfs(a+1,l);
l-=mp[p[a]][i];
vis[i]--;
}
}
}
int main()
{
cin>>n;
char a;
per(i,1,n) cin>>s[i];
cin>>a;
per(i,1,n)//预处理
{
if(s[i][0]==a)
mp[0][i]=s[i].length();//可以接龙头的长度
}
per(i,1,n)
{
per(j,1,n)
{
mp[i][j]=fun(s[i],s[j]);//判断是否可连接,返回去重后的长度
//cout<<mp[i][j]<<"*";
} //cout<<endl;
}
dfs(0,0);
cout<<ans;
return 0;
}
C.乒乓球
题目描述
国际乒联现在主席沙拉拉自从上任以来就立志于推行一系列改革,以推动乒乓球运动在全球的普及。其中11分制改革引起了很大的争议,有一部分球员因为无法适应新规则只能选择退役。华华就是其中一位,他退役之后走上了乒乓球研究工作,意图弄明白11分制和21分制对选手的不同影响。在开展他的研究之前,他首先需要对他多年比赛的统计数据进行一些分析,所以需要你的帮忙。
华华通过以下方式进行分析,首先将比赛每个球的胜负列成一张表,然后分别计算在11分制和21分制下,双方的比赛结果(截至记录末尾)。
比如现在有这么一份记录,(其中W表示华华获得一分,L表示华华对手获得一分):
WWWWWWWWWWWWWWWWWWWWWWLW
在11分制下,此时比赛的结果是华华第一局11比0获胜,第二局11比0获胜,正在进行第三局,当前比分1比1。而在21分制下,此时比赛结果是华华第一局21比0获胜,正在进行第二局,比分2比1。如果一局比赛刚开始,则此时比分为0比0。
你的程序就是要对于一系列比赛信息的输入(WL形式),输出正确的结果。
输入
每个输入文件包含若干行字符串(每行至多20个字母),字符串有大写的W、L和E组成。其中E表示比赛信息结束,程序应该忽略E之后的所有内容。
输出
输出由两部分组成,每部分有若干行,每一行对应一局比赛的比分(按比赛信息输入顺序)。其中第一部分是11分制下的结果,第二部分是21分制下的结果,两部分之间由一个空行分隔。
样例输入
WWWWWWWWWWWWWWWWWWWW WWLWE
样例输出
11:0 11:0 1:1 21:0 2:1
提示
注意:乒乓球比赛每局结束规则:一方胜另一方2球,本局结束,记录比分比赛双方任一一方达到11分或21分且领先对手两分,此时比赛结束(可能存在41:40这种情况)
思路:真的不想吐槽,比赛时题面有问题后面才改的,害我wa12发。2种情况,a或b到达11,且相差大于等于2,ab都大于11,且相差大于等于2.然后直接模拟即可。
代码如下:
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string>
#include<set>
#include<math.h>
#include<map>
#include<string.h>
#include<stack>
#include<queue>
#define per(i,a,b) for(int i=a;i<=b;++i)
#define rep(i,a,b) for(int i=a;i>=b;--i)
#define inf 0x3f3f3f
using namespace std;
int main()
{
char ch,s[1000000];
int a=0,b=0,k=0,A=0,B=0;
while(ch=getchar())
{
//if(ch=='\n') continue;
s[k]=ch;k++;
if(ch=='E')
{
printf("%d:%d\n",a,b);a=0,b=0;
break;
}
if(ch=='W') a++;
if(ch=='L') b++;
if((a>=11&&abs(a-b)>=2)||(abs(b-a)>=2&&b>=11)||(abs(a-b)==2&&a>=11&&b>=11))
{
printf("%d:%d\n",a,b);
a=0,b=0;
}
}
printf("\n");
per(i,0,k-1)
{
//cout<<s[i]<<"*";
if(s[i]=='E')
{
printf("%d:%d\n",a,b);
break;
}
if(s[i]=='W') a++;
if(s[i]=='L') b++;
if((a>=21&&abs(a-b)>=2)||(b>=21&&abs(b-a)>=2)||(a>=21&&b>=21&&abs(a-b)==2))
{
printf("%d:%d\n",a,b);
a=0,b=0;
}
}
return 0;
}
D.亲戚
题目描述
或许你并不知道,你的某个朋友是你的亲戚。他可能是你的曾祖父的外公的女婿的外甥女的表姐的孙子。如果能得到完整的家谱,判断两个人是否亲戚应该是可行的,但如果两个人的最近公共祖先与他们相隔好几代,使得家谱十分庞大,那么检验亲戚关系实非人力所能及。在这种情况下,最好的帮手就是计算机。为了将问题简化,你将得到一些亲戚关系的信息,如Marry和Tom是亲戚,Tom和Ben是亲戚,等等。从这些信息中,你可以推出Marry和Ben是亲戚。请写一个程序,对于我们的关于亲戚关系的提问,以最快的速度给出答案。
输入
输入由两部分组成。
第一部分以N,M开始。N为问题涉及的人的个数(1≤N≤20000)。这些人的编号为123… N。下面有M行(1≤M≤1 000 000),每行有两个数ai bi,表示已知ai和bi是亲戚。
第二部分以Q开始。以下Q行有Q个询问(1≤Q≤1 000 000),每行为ci di,表示询问ci和di是否为亲戚。
输出
对于每个询问ci di,输出一行:若ci和di为亲戚,则输出“Yes”,否则输出“No”。
样例输入
10 7 2 4 5 7 1 3 8 9 1 2 5 6 2 3 3 3 4 7 10 8 9
样例输出
Yes No Yes
思路:并查集+压缩路径至根节点呗。
代码如下:
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string>
#include<set>
#include<math.h>
#include<map>
#include<string.h>
#include<stack>
#include<queue>
#define per(i,a,b) for(int i=a;i<=b;++i)
#define rep(i,a,b) for(int i=a;i>=b;--i)
#define inf 0x3f3f3f
using namespace std;
long long int p[20005],n;
void init()
{
per(i,1,n)
{
p[i]=i;
}
}
long long int findset(long long int v)
{
long long int t1,t2=v;
while(v!=p[v])
{
v=p[v];
}
while(t2!=p[t2])
{
t1=p[t2];
p[t2]=v;
t2=t1;
}
return v;
}
void bin(long long int a,long long int b)
{
long long int a1=findset(a);
long long int b1=findset(b);
if(a1!=b1)
{
p[a1]=b1;
}
}
int main()
{
long long int m,t,a,b;
cin>>n>>m;
init();
while(m--)
{
cin>>a>>b;
bin(a,b);
}
//per(i,1,n) cout<<p[i]<<"*";
cin>>t;
while(t--)
{
cin>>a>>b;
while(p[a]!=a)
{
a=p[a];
}
while(p[b]!=b)
{
b=p[b];
}
if(a==b) printf("Yes\n");
else printf("No\n");
}
return 0;
}
E.回文数
题目描述
我们把从左往右和从右往左念起来相同的数字叫做回文数。例如,75457就是一个回文数。
当然某个数用某个进制表示不是回文数,但是用别的进制表示可能就是回文数。
例如,17是用十进制表示的数,显然它不是一个回文数,但是将17用二进制表示出来是10001,显然在二进制下它是一个回文数。
现在给你一个用十进制表示的数,请你判断它在2~16进制下是否是回文数。
输入
输入包含多组测试数据。每组输入一个用十进制表示的正整数n(0<n<50000),当n=0时,输入结束。
输出
对于每组输入,如果n在2~16进制中的某些进制表示下是回文数,则输出“Number i is palindrom in basis ”,在后面接着输出那些进制。其中i用n的值代替,后面输出的进制中,每两个数字之间空一个。
如果n在2~16进制的表示下都不为回文数,则输出“Number i is not a palindrom”,其中i用n的值代替。
样例输入
17 19 0
样例输出
Number 17 is palindrom in basis 2 4 16 Number 19 is not a palindrom
思路:模拟即可,没有坑点
代码如下:
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string>
#include<set>
#include<math.h>
#include<map>
#include<string.h>
#include<stack>
#include<queue>
#define per(i,a,b) for(int i=a;i<=b;++i)
#define rep(i,a,b) for(int i=a;i>=b;--i)
#define inf 0x3f3f3f
using namespace std;
int n;
int fun(int k)
{
int s[100000];
int z=1,h=n;
while(h!=0)
{
s[z]=h%k;//cout<<s[z];
h=h/k;
z++;
}
//cout<<"*";
int i=1,j=z-1;
if(z==2) return 1;
if(j==2)
{
if(s[1]==s[2]) return 1;
else return 0;
}
//cout<<z<<"*";
for(i=1,j=z-1;j>i;++i,--j)
{
if(s[i]!=s[j]) return 0;
}
return 1;
}
int main()
{
while(cin>>n&&n!=0)
{
int p[17],l=0;
per(i,2,16)
{
if(fun(i)==1) p[l]=i,l++;
}
if(l==0) printf("Number %d is not a palindrom\n",n);
else
{
printf("Number %d is palindrom in basis",n);
per(i,0,l-1)
{
printf(" %d",p[i]);
}
printf("\n");
}
}
return 0;
}
F.最优布线问题
题目描述
学校有n台计算机,为了方便数据传输,现要将它们用数据线连接起来。两台计算机被连接是指它们间有数据线连接。由于计算机所处的位置不同,因此不同的两台计算机的连接费用往往是不同的。
当然,如果将任意两台计算机都用数据线连接,费用将是相当庞大的。为了节省费用,我们采用数据的间接传输手段,即一台计算机可以间接的通过若干台计算机(作为中转)来实现与另一台计算机的连接。
现在由你负责连接这些计算机,任务是使任意两台计算机都连通(不管是直接的或间接的)。
输入
输入文件wire.in,第一行为整数n(2<=n<=100),表示计算机的数目。此后的n行,每行n个整数。第x+1行y列的整数表示直接连接第x台计算机和第y台计算机的费用。
输出
输出文件wire.out,一个整数,表示最小的连接费用。
样例输入
3 0 1 2 1 0 1 2 1 0
样例输出
2
提示
注:表示连接1和2,2和3,费用为2
思路:最小生成树,没有坑点。
代码如下:
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string>
#include<set>
#include<math.h>
#include<map>
#include<string.h>
#include<stack>
#include<queue>
#define per(i,a,b) for(int i=a;i<=b;++i)
#define rep(i,a,b) for(int i=a;i>=b;--i)
#define inf 0x3f3f3f
using namespace std;
int n,p[1000][1000],p1[1000][1000];
int d[1000];
int vis[1000]={0};
int prim()
{
fill(d,d+n+1,inf);
d[0]=0;
int s=0;
per(i,0,n-1)
{
int u=-1,minn=inf;
per(j,0,n-1)
{
if(vis[j]==0&&d[j]<minn)
{
u=j;
minn=d[j];
}
}
if(u==-1) return -1;
vis[u]=1;
s+=d[u];
per(v,0,n-1)
{
if(vis[v]==0&&p[u][v]!=inf&&p[u][v]<d[v])
{
d[v]=p[u][v];
}
}
}
return s;
}
int main()
{
int a,b,c;
cin>>n;
per(i,0,n-1)
{
per(j,0,n-1)
{
cin>>p[i][j];
}
}
/*per(i,1,n)
{
per(j,i+1,n)
{
p[i][j]=p1[i+1][j];
}
}*/
printf("%d",prim());
return 0;
}
G.修路
题目描述
SNJ位于HB省西部一片群峰耸立的高大山地,横亘于A江、B水之间,方圆数千平方公里,相传上古的神医在此搭架上山采药而得名。景区山峰均在海拔3000米以上,堪称"华中屋脊"。SNJ是以秀绿的亚高山自然风光,多样的动植物种,人与自然和谐共存为主题的森林生态区。
SNJ处于中国地势第二阶梯的东部边缘,由大巴山脉东延的余脉组成中高山地貌,区内山体高大,高低不平。 交通十分不便。
最近,HB省决定修一条从YC市通往SNJ风景区的高速公路。经过勘测分析,途中需要经过高度分别为H1,H2,……Hn的N个山区。由于高低不平,除正常的修路开支外,每段还要多出高度差|Hi - Hi-1|*X万元的斜坡费用。Dr. Kong 决定通过填高一些区域的高度来降低总的费用。当然填高也是需要一些费用的。每填高Y单位,需要付出Y2万元费用。
你能否帮Dr. Kong做出一个规划,通过部分填高工程改造,使得总的费用降下来。
输入
第一行: T 表示以下有T组测试数据 ( 1≤ T ≤8 ) 对每组测试数据, 第一行:N X (2 ≤ N ≤100,000 1≤ X ≤100) 第二行:N个整数,分别表示N个区域的高度Hi ( 1<=Hi<=100 i=1…. n)
输出
对每组测试数据,输出占一行,一个整数,即经过部分填高工程改造后的最少费用。
样例输入
1 5 2 2 3 5 1 4
样例输出
15
思路:河南省赛原题,鄙人不擅dp,暂时不会。
H.N皇后问题
题目描述
在N*N(1<N<=9)的棋盘上放置N个皇后而彼此不受攻击(即在棋盘的任一行,任一列和任一对角线上不能放置2个皇后),编程求解所有的摆放方法。
输入
一个整数n(1<n<=9)
输出
若有解,输出若干行,每行n个数,依次表示第i个皇后的列号
若无解,输出 “no”
样例输入
4
样例输出
2 4 1 3 3 1 4 2
思路:暴力搜索,记录一下位置。其实这题和全排列一模一样。
代码如下:
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string>
#include<set>
#include<math.h>
#include<map>
#include<string.h>
#include<stack>
#include<queue>
#define per(i,a,b) for(int i=a;i<=b;++i)
#define rep(i,a,b) for(int i=a;i>=b;--i)
#define inf 0x3f3f3f
using namespace std;
int vis[10],n,p[10],s=0;
int p1[10];
void fun(int x)
{
if(x==n+1)
{
int fag=1;
per(i,1,n)
{
per(j,i+1,n)
{
if(abs(i-j)==abs(p[i]-p[j]))
fag=0;
}
}
if(fag)
{
s++;
per(j,1,n) printf("%d ",p1[j]);
printf("\n");
return;
}
}
per(i,1,n)
{
if(vis[i]==0)
{
p[i]=x;
vis[i]=1;
p1[x]=i;
fun(x+1);
vis[i]=0;
}
}
}
int main()
{
cin>>n;
fun(1);
if(s==0) printf("no");
return 0;
}
总结:开学后状态太差了,开场数组开小了wa6发,题面有问题wa9发,没输出no没压缩路径wa4发,回文对称都能wa5发........
虽然会,但是实在是不能忍受,接下来找回状态好好备战区域赛。