湖南农业大学 2014年 ACM 校赛Problem 2014 /2/23 星期日 12:30-17:30A.搜素 1794.查找指定的字符串 B.链表 1795 争当幸运儿 C.Date 1796 时间日期 JAVA D.筛选法 1797 反素数 E.模拟 1798 照片冲印 F.动归 G.计算几何 H. 位运算 UTF-8 转Unicode |
A .查找指定的字符串
Description
在二维字符阵列中寻找指定的字符串。
Input
前两行分别指示字符矩阵的宽w和高h(1<=w<=7 且 1<=h<=7)。接下来的h行每行w个字符便是字符矩阵的内容,再下面的1行为要寻找的字符串的数目n(n<4),其后的n行便是要寻找的字符串,每个字符串不会超过7个字符。
Output
n行,每行保存1个字符串的位置。位置的格式形如(1,2)->(2,6),意为该字符串首字母在字符矩阵中的位置是第1列2行,尾字母在字符矩阵中的位置是第2列6行。
Sample Input
5
5
ABCDO
FHHIL
KILLL
QKSOE
VWKYH
3
KKK
KILL
HELLO
Sample Output
(1,3)->(3,5)
(1,3)->(4,3)
(5,5)->(5,1)
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
#define M 9
char graph[M][M];
char temp[M];
int w,h;
struct point{
int x,y;
bool ok()
{
return (x>=0&&x<h&&y>=0&&y<w);
}
};
point s,e,now;
int dir[8][2]={{-1,0},{0,1},{1,0},{0,-1},{-1,-1},{-1,1},{1,1},{1,-1}};
/* 上 右 下 左 左斜上 右斜上 右斜下 左斜下*/
int mysearch(int i,int j)
{
int len=strlen(temp);
if(len==1){e.x=s.x; e.y=s.y;return 1;}
for(int i=0;i<8;i++)
{
now.x=s.x+dir[i][0];
now.y=s.y+dir[i][1];
int k=1;
while(now.ok()&&graph[now.x][now.y]==temp[k++])
{
if(k==len){e.x=now.x;e.y=now.y;return 1;}
now.x+=dir[i][0];
now.y+=dir[i][1];
}
}
return 0;
}
void solve()
{
for(int i=0;i<w;i++)
for(int j=0;j<h;j++)
if(graph[i][j]==temp[0])
{
s.x=i;s.y=j;
if(mysearch(i,j))
{
printf("(%d,%d)->(%d,%d)\n",s.y+1,s.x+1,e.y+1,e.x+1);
return ;
}
}
}
int main()
{
int n;
while(~scanf("%d%d",&w,&h))
{
for(int i=0;i<h;i++)
{
scanf("%s",graph[i]);
}
scanf("%d",&n);
while(n--)
{
scanf("%s",temp);
solve();
}
}
return 0;
}
B 1795 争当幸运儿
Description
n个人围成一圈,并依次编号1~n。从编号为1的人开始,按顺时针方向每隔2人选出1个,剩下的人重新围成一圈,如此循环直到剩下两人,这剩下的两人就是幸运儿。如果你想成为最后两个幸运儿,请问开始时应该站在什么位置?(设3<=n<=50)
Input
开始时的人数n
Output
第1行是选出顺序,第2行是两名幸运儿开始的位置(按升序排列),位置编号之间用一个空格分开。
Sample Input
13
Sample Output
3 6 9 12 2 7 114 10 5 1
8 13
HINT
注意:输出的第一行末尾有一个空格。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
int n;
struct node{
int data;
node* next;
}*pre,*p,*head;
void creat()
{
p=new node();
p->data=1;
head=p;
for(int i=2;i<=n;i++)
{
pre=p;
p=new node();
p->data=i;
pre->next=p;
}
p->next=head;
}
void myshow()
{
for(int i=1;i<=n-2;i++)
{
p=p->next->next;
pre=p;
p=p->next;
pre->next=p->next;
printf("%d ",p->data);
delete p;
p=pre;
}
printf("\n");
if(p->data < p->next->data)
printf("%d %d\n",p->data,p->next->data);
else
printf("%d %d\n",p->next->data,p->data);
delete p->next;
delete p;
}
int main()
{
while(~scanf("%d",&n))
{
creat();
myshow();
}
return 0;
}
C 时间日期
Description
计算机系统对当前系统时间的表示采用了一种比较奇怪的方式,它记录了相对于1970年元月1日零时零分零秒至当前的毫秒数。如果时间在1970年之前,那么此值为负。1970年元月1日00:00:00称为UNIX元年(UNIX epoch),因为UNIX操作系统是在概念正式发布。现在给定一个整数,表示距UNIX元年的毫秒数,请编程计算出它所表示的年月日时分秒、毫秒(此处的毫秒为一秒内的剩余的毫秒数)、星期几。
Input
若干行,每行一个整数t(-2208988800000≤t≤4102444799999),表示毫秒数
Output
按照样例的格式输出,每行输出一个结果。年份按4位输出,月日时分秒按2位输出,秒后为一个小数点".",接着输出毫秒按3位输出,最后输出星期几。星期天用0表示,星期一用1表示,... ,星期六用6表示。注意,每行输出的末尾没有空格。
Sample Input
0
1392863010349
Sample Output
1970 01 01 00:00:00.000 4
2014 02 20 02:23:30.349 4
//package acm_code;
import java.util.*;
import java.text.*;
public class GetDateTime {
/**
* input: 681601001000
* 标准输出:1991 08 07 22:36:41.000 3
* 我的输出:1991 08 07 21:36:41.000 3
*/
/**
* @param 输入一个long型的系统毫秒值
* @throws ParseException
*/
public static void main(String[] args) throws ParseException{
Scanner in=new Scanner(System.in);
//设置默认时区为格林威治时间 0时
TimeZone.setDefault(TimeZone.getTimeZone("GMT+0:00"));
System.out.println(TimeZone.getDefault());
DateFormat df=new SimpleDateFormat("yyyy MM dd HH:mm:ss.SSS ");
Calendar cal=Calendar.getInstance();
Date date=new Date(0L);
long n;
while(in.hasNextLong())
{
n=in.nextLong()-28800000;
date.setTime(n);
String prefix =df.format(date);
//下面求星期几
cal.setTimeInMillis(n);
int week=cal.get(Calendar.DAY_OF_WEEK)-1;
System.out.println(prefix+week);
}
in.close();
}
}
D 反素数
Description
n为反素数是指n本身是素数,将反向构成的数也是素数,但n不是回文数。例如13是反素数,但是131就不是反素数,因为它是回文数。
Input
第一行有一个整数k(1<=k<=100),表示测试用例的个数,其后的k行,没行有两个整数m,n(1<=m<N<=1000000)。< p>
Output
请输出每个[m,n]区间内的所有反素数。如果没有,则输出"not found"。请注意输出的格式:两个测试用例之间的有且仅有一个空行。每个测试用例的输出中,每行输出10个反素数,同行的两个反素数之间用1个空格分隔,每行的行尾没有空格。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
#include <time.h>
#define M 1000000
bool prime[M+5];
int ans[M/10],len=0;
void getPrime()
{
int i,j;
//memset(prime,0,sizeof(prime));
for(i=2;i<=sqrt(M);i++)
if(!prime[i])
{ for(j=i*i;j<=M;j+=i)
prime[j]=1;
}
}
int convert(int x)
{
int l=0,flag=0,temp=0;
int a[6];
while(x)
{
a[l++]=x%10;
x/=10;
}
for(int i=0;i<l/2;i++)
if(a[i]!=a[l-1-i])
{flag=1; break;}
if(flag==0)return 0;//是回文数
for(int i=0;i<l;i++)
temp=temp*10+a[i];
// if(l==2)printf("temp==%d\n",temp);
if(!prime[temp])return 1;//是素数
return 0;
}
void solve()
{
for(int i=12;i<M;i++)
if(!prime[i])
{
if(convert(i))
ans[len++]=i;
}
// printf("78385总个数为:%d\n",len);
}
void show(int a,int b)
{
int first=1,cnt=0,i=0;
while(a>ans[i])i++;
while(ans[i]<=b&&i<len)
{
if(first)
{ printf("%d",ans[i]);cnt++;first=0;}
else
{
if(cnt%10==0)printf("\n");
else printf(" ");
printf("%d",ans[i]);
cnt++;
}
i++;
}
if(first){printf("not found\n");return;}
//结束当前行
printf("\n");
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int n,a,b;
getPrime();
solve();
scanf("%d",&n);
while(n--)
{
scanf("%d%d",&a,&b);
show(a,b);
if(n!=0)printf("\n");
}
return 0;
}
E 照片冲印
Description
某次班级集体活动中,大家玩的非常开心,并且由一位擅长摄影的同学拍摄许许多多的照片,活动结束后,大家需要冲印本次活动的照片。为了方便冲印,将所有的照片从1开始顺序编号。然后每位同学提出自己需要冲印的照片。通过如下三种方式指定:(1)单个数字m(1<=m<=10000),表示冲印此编号照片1张。(2)如果需要的照片编号连续,可以使用“m-n”的表示(1<=m<N<=10000)。(3)如果某个同学需要的编号为N的照片冲印X张,这可用N*X表示。照片编号之间用逗号分隔。 p 现在需要按两种方式处理此数据,一是为照相馆准备的数据,照相馆在冲印照片时,需要知道每张照片的冲印数量;二是为负责收取冲印费的同学准备的数据。冲印照片是收费的,由每位冲印照片的同学付费,为了方便收费,需要知道每个同学冲印照片的张数。<>
Input
第一行包含一个整数k(1<=k<=1000),表示测试用例的个数。其后共有n个测试用例。每个测试用例的第一行为需要照片的人数n(1<=n<=100)。其后的n行中,每行包含用逗号分隔的表示所需照片编号,第1行表示1号同学需要的照片,第2行表示2号同学需要的照片,依此类推。最大照片编号小于等于10000。
Output
每个测试用例输出2行。第一行输出需要冲印的每张照片的数量,如果照片数量为1则输出该编号,如果大于1则输出“编号*张数”,按照片编号从小到大排列,不需要冲洗的照片不要列出来。第二行顺序地输出每个同学冲印照片的张数。i注意,同行两项输出之间用1个空格分隔,但是每行输出的末尾没有空格。测试用例的输出之后有1个空行。
Sample Input
2
1
1-10
3
2,5-12,15*3,14,6-8
1,3*2,7,3*4,5,2,4,3
10*2,15,8,6-11
Sample Output
1 2 3 4 5 6 7 8 9 10
10
1 2*2 3*7 4 5*2 6*3 7*4 8*4 9*2 10*4 11*2 12 14 15*4
16 12 10
//package acm_code;
import java.util.Scanner;
public class Main {
public static int n;
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
int cases;
int[] photo=new int[10002];
int[] people=new int[1002];
String str;
int maxn=0;
cases=in.nextInt();
while(cases-->0)
{
for(int i=1;i<10002;i++)
photo[i]=0;
for(int i=1;i<1002;i++)
people[i]=0;
n=in.nextInt();
in.nextLine();
for(int i=1;i<=n;i++)
{
str=in.nextLine();
String []token=str.split(",");
for(int j=0;j<token.length;j++)
{
if(token[j].contains("-"))
{
String [] b=token[j].split("-");
int a=Integer.parseInt(b[0]);
int c=Integer.parseInt(b[1]);
for(int k=a;k<=c;k++)
photo[k]++;
people[i]+=c-a+1;
if(maxn<c)maxn=c;
}else if(token[j].contains("*")){
String [] b=token[j].split("[*]");
int a=Integer.parseInt(b[0]);
int c=Integer.parseInt(b[1]);
photo[a]+=c;
people[i]+=c;
if(maxn<a)maxn=a;
}else {
int a=Integer.parseInt(token[j]);
people[i]++;
photo[a]++;
if(maxn<a)maxn=a;
}
}
}
boolean first=true;
for(int i=1;i<=maxn;i++)
if(photo[i]>0)
{
if(first){
if(photo[i]==1) System.out.print(i);
else System.out.print(i+"*"+photo[i]);
first=false;
}else {
System.out.print(" ");
if(photo[i]==1) System.out.print(i);
else System.out.print(i+"*"+photo[i]);
}
}
System.out.print("\n");
for(int i=1;i<=n;i++)
{
if(i!=1)System.out.print(" ");
System.out.print(people[i]);
}
System.out.print("\n\n");
}
in.close();
}
}
H UTF-8 转Unicode
#include <stdio.h>
int main()
{
int n,temp,ans;//数据最大为32位
int k;
scanf("%d",&k);
while(k--)
{
scanf("%x",&n);
if(n<0x10000)printf("%04X\n",n);
else{
n=n-0x10000;
temp=n&0x3FF;//取低10位
ans=((n-temp)<<6)|0xD800DC00|temp;//分别填充
printf("%08X\n",ans);
}
}
return 0;
}