3-ACM-作业6~7

1054 平方数

给你一个整数集合A(无重复元素),如果x,y都属于A,且y=xx,那么组成一个数对,请找出这个集合中满足条件的数对的个数。比如说集合A={2,3,4},则只有4=22,则答案为1。

输入
每个样例占2行,第一行为一个非负整数n,n<=1000,为集合中元素的个数,如果n为0则输入结束。第二行为n个整数,为集合的元素,所有的元素为非负整数,且<=100,000,000,两个整数之间有一个空格隔开。

注意:别写平方,即别写两个数相乘,极易溢出。
//定义为全局变量调用会增加运行时间。
//int范围是21亿,9个0是十亿。

1103 日期

给出一个日期,请计算这天是这一年的第几天? 输入 第一行是一个整数N,表示样例的个数,以后每行一个日期,日期格式满足“YYYY-MM-DD”的格式(即年4位,月2位,日期2位)。 输出 每行输出一个整数,即第几天,输入保证日期的合法性。

Sample Input
3
2000-02-29
2001-02-01
2001-02-28

Sample Output
60
32
59

闰年就w[2]=29,但是每次循环完后,要把w[2]又归零为28.
用一个数组把各个月的天数存下来。

#include
int main(){
    int ans,n,i,a,b,c;
    int w[15]={0,31,28,31,30,31,30,31,31,30,31,30,31};
    scanf("%d",&n);
    while(n--){
        ans=0;
        scanf("%d-%d-%d",&a,&b,&c);
        if((a%4==0&&a%100!=0)||a%400==0)  w[2]=29;
        for(i=1;i<=b-1;i++)  ans+=w[i];
        ans+=c;
        printf("%d\n",ans);
        w[2]=28;
    }
    return 0;
}

1148 三角形

给一个序列,按下面的方式进行三角形累加,求其和值。 比如序列为 1,2,3,4,5

1 2 3 4 5
3 5 7 9
8 12 16
20 28
48
输入
有多组样例。每个样例的第一行是一个整数N(1≤N≤100),表示序列的大小, 如果N为0表示输入结束。这个样例不需要处理。 第二行是N个整数,每个整数处于[0,100]之间。

输出
每行输出一个样例的结果,由于结果可能很大,请将结果对2013取模。

样例输入
5
1 2 3 4 5
2
1 1
0

样例输出
48
2

思路:用一个1维数组即可。

#include
int main(){
    int ans,n,i,a,b,c;
    int w[15]={0,31,28,31,30,31,30,31,31,30,31,30,31};
    scanf("%d",&n);
    while(n--){
        ans=0;
        scanf("%d-%d-%d",&a,&b,&c);
        if((a%4==0&&a%100!=0)||a%400==0)  w[2]=29;
        for(i=1;i<=b-1;i++)  ans+=w[i];
        ans+=c;
        printf("%d\n",ans);
        w[2]=28;
    }
    return 0;
}

1105 分数加减法

涉及到分数相减为负数时,就拿一个变量做符号位来处理会很方便。

1108 a+b

请计算a+b,但a和b是按不同的进制给出的。进制最小为2进制,最大为62进制,其中使用A-Z依次表示10到35,a-z表示36-61。请写出a+b的结果,结果按十进制输出。 输入 第一行是一个整数N,表示有多少个测试样例,以后每行是一个样例,每行是4个部分,分别为a的值,a的进制,b的值,b的进制。其中值都是用一个字符串表示,进制都是一个整数。4个部分之间用一个空格隔开,保证输入的合法,a、b和a+b的值都在-231到231-1之间。 输出 每行输出一个样例的结果。

Sample Input
2
1000 2 1F 16
-1 10 20 3

Sample Output
39
5

思路:这道题有个负数就比较麻烦,就要讨论四次来进行相应变换,也没想出很好办法来解决,这种题就直接讨论得了,确实比较麻烦。又不是算法的问题,代码多写点也没事,没有特别优化问题也不大,毕竟也就四种情况。

#include 
#include 

inline int shu(char c){
    if('0' <= c && c <= '9')
        return c - '0';
    if('A' <= c && c <= 'Z')
        return c - 'A' + 10;
    if('a' <= c && c <= 'z')
        return c - 'a' + 36;
}

int main()
{
    int n;
    char s[66];
    __int64 ans, tmp, i, k;

    scanf("%d", &n);
    while(n--){
        scanf("%s%I64d", s, &k);
        tmp = 0;
        if(s[0] == '-'){
            for(i = 1; i < strlen(s); i++)
                tmp = tmp * k + shu(s[i]);
            ans = -1 * tmp;
        }
        else{
            for(i = 0; i < strlen(s); i++)
                tmp = tmp * k + shu(s[i]);
            ans = tmp;
        }

        scanf("%s%I64d", s, &k);
        tmp = 0;
        if(s[0] == '-'){
            for(i = 1; i < strlen(s); i++)
                tmp = tmp * k + shu(s[i]);
            tmp = -1 * tmp;
        }
        else{
            for(i = 0; i < strlen(s); i++)
                tmp = tmp * k + shu(s[i]);
        }
        printf("%I64d\n", ans + tmp);
    }
    return 0;
}

1114 字符串逆序

给你一个字符串,请将其第K个字符开始的长度为L的子串进行逆序。

就算这题再简单也要想清楚再写!
还要看清题目!!!不然模拟题是很容易出错的!!!
这道题我居然写了半个小时!

1178 Rectangle

给你两个平行于坐标轴的矩形,请判断两者是不是相交(面积有重合的部分)?

输入
第一行是一个整数K,表示样例数。 每个样例占两行,每行是4个整数,表示一个矩形的对角线点的坐标,坐标值为0到1,000之间。

输出
每个样例输出一个结果,相交输出Yes,否则输出No。

样例输入
2
0 0 1 1
1 1 2 2
0 0 2 2
1 1 3 3

样例输出
No
Yes

思路:降维处理,如果在x轴和y轴上都有重合的部分,则相交。

#include
int main(){
     
    int k,x1,y1,x2,y2,x3,y3,x4,y4,e;
    scanf("%d",&k);
    while(k--){
     
        scanf("%d%d%d%d%d%d%d%d",
        &x1,&y1,&x2,&y2,&x3,&y3,&x4,&y4);
        if(y1>y2){
     
            e=y2;y2=y1;y1=e;
            e=x2;x2=x1;x1=e;
        }
        if(y3>y4){
     //y3>y4的时候,x3是小于x4的,而不是x3>x4。
            e=y3;y3=y4;y4=e;
            e=x3;x3=x4;x4=e;
        }
        if(y4>y1&&y2>y3&&x2>x3&&x4>x1)  printf("Yes\n");
        else  printf("No\n"); 
    }
    return 0;
} 

这道题写的时候一直wa,是因为思路一开始没有想清楚,想当然了。写代码这块一定不能想当然啊!!!一定要很确定!细致!

1258 矩阵

编写一个程序,将1~n2按行依次填入n×n的矩阵,执行若干条行或者列的循环移动的指令,再将数字按行依次取出。

指令如下:

指令 含义
L x y x行循环左移y次
R x y x行循环右移y次
U x y x列循环上移y次
D x y x列循环下移y次
输入
第一行是一个整数K,表示样例的个数。 每个样例的第一行是两个整数n(1≤n≤10)和m(1≤m≤1000),分别表示矩阵的大小和指令的条数。
以后的m行是m条指令,矩阵的行列按1开始计数,指令满足1≤x≤n,1≤y≤n−1。

输出
每行输出一个样例的结果,数字之间用一个空格隔开,行末无空格。

样例输入
4
3 1
L 1 1
3 1
R 1 1
3 1
U 1 1
3 1
D 1 1
样例输出
2 3 1 4 5 6 7 8 9
3 1 2 4 5 6 7 8 9
4 2 3 7 5 6 1 8 9
7 2 3 1 5 6 4 8 9

思路:这道题我想用倍增法写,结果把自己搞蒙了。

1267 Matrix

Matrix
题目描述
一个矩阵An×m,矩阵按行依次为1∼nm。若干种指令,指令集如下: (以3×3的初始矩阵为例,结果矩阵列中为初始矩阵执行这条指令后的矩阵结果)

指令 含义 指令示例 结果矩阵
IN n m 初始化为n×m的矩阵 IN 3 3 1 2 3
4 5 6
7 8 9
SR x y 交换矩阵的x,y行 SR 1 2 4 5 6
1 2 3
7 8 9
SC x y 交换矩阵的x,y列 SC 1 2 2 1 3
5 4 6
8 7 9
TR 矩阵转置 TR 1 4 7
2 5 8
3 6 9
FR 上下镜像反转 FR 7 8 9
4 5 6
1 2 3
FC 左右镜像反转 FC 3 2 1
6 5 4
9 8 7
PR 输出矩阵 PR 1 2 3
4 5 6
7 8 9
现在给你一个合法的指令序列(条数不超过1000,矩阵行列最大不超过10),请执行对应指令。

输入
每行输入一条指令。

输出
对于每个PR命令,输出矩阵。矩阵元素之间有一个空格,行末无空格,最后输出一个空行。

思路:写一个交换两个数的函数,价格循环就可以,然后矩阵的转置不能用这个函数,要用到另一个同样的数组来做。

注意!!!

模拟题一开始要想到所有情况!!!!不然后面调试真的很慢!!!!尤其是只用一个主函数来写,不用其他函数。
puts("\n")这样子会输出两个空行!!
用函数来写的好处就是,真的能大大降低出粗的概率。缺点就是运行时间增加的有点多。

代码个人感觉写得还算简洁,就放出来了。
法一:不用函数,用公式。

#include
void swi(int *a,int *b){
     
	int e;
	e=*a,*a=*b;*b=e;
}
int main(){
     
	char arr[4];
	int x,y,i,j,n,m,p,a[11][11],a2[11][11];
	while(~scanf("%s",arr)){
     
		if(arr[0]=='I'){
     
			scanf("%d%d",&n,&m);
			p=1;
			for(i=0;i<n;i++){
     
				for(j=0;j<m;j++,p++){
     
					a[i][j]=p;
				}
			}
		}
		if(arr[0]=='S'&&arr[1]=='R'){
     
			scanf("%d%d",&x,&y);
			for(i=0;i<m;i++)  swi(&a[x-1][i],&a[y-1][i]);
		}
		if(arr[0]=='S'&&arr[1]=='C'){
     
			scanf("%d%d",&x,&y);
			for(i=0;i<n;i++)  swi(&a[i][x-1],&a[i][y-1]);
		}
		if(arr[0]=='T'){
     //不能用到swi的方式,因为不止n阶矩阵,
		//说明一开始想清楚所有情况,真的比后面调试快得多啊!! 
			for(i=0;i<n;i++){
     
				for(j=0;j<m;j++)  a2[i][j]=a[i][j];
			}
			for(i=0;i<n;i++){
     
				for(j=0;j<m;j++){
     
					a[j][i]=a2[i][j];
				} 	
			}
			p=n;n=m;m=p;
		}
		if(arr[0]=='F'&&arr[1]=='R'){
     
			for(i=0;i<n/2;i++){
     
				for(j=0;j<m;j++)  swi(&a[i][j],&a[n-i-1][j]);  	
			}  
		}
		if(arr[0]=='F'&&arr[1]=='C'){
     
			for(j=0;j<m/2;j++){
     
				for(i=0;i<n;i++)  swi(&a[i][j],&a[i][m-1-j]);  	
			}  
		}
		if(arr[0]=='P'){
     
			for(i=0;i<n;i++){
     
				for(j=0;j<m-1;j++)  printf("%d ",a[i][j]);
				printf("%d\n",a[i][m-1]);
			}
			puts("");//puts自带换行输出。 
		}
	}
	return 0;
}

法2,自己写的一个函数,跟谢大的对比,发现为了减少出错和增强可读性,不如把所有的处理都放到一个函数中,主函数就不需要怎么对数据处理了。

#include//写函数的好处就是大大降低了出错误的概率!! 
void swi(int arr[],int der,int y,int n){
	int i;
	for(i=0;in-1;i--)  arr[i]=arr[i-y];
	}
	else{//左移 
		for(i=n;i<2*n;i++)  arr[i]=arr[i+y];
	}
}
int main(){
	int arrp[11][11],arr[44];
	int i,j,p,k,n,m,x,y;
	char c;
	scanf("%d",&k);
	while(k--){
		scanf("%d%d",&n,&m);
		p=1;
		for(i=0;i

高能!!!谢大的!!!

#include 
#define FU(i,n) for(int i=0;i<(n);i++)
#define N 10
void shift(int n,int (*a)[N],int x,int y,int dx,int dy,int s){
	int b[n<<1],cx=x,cy=y;
	FU(i,n){
		b[i] = b[i+n] = a[cx][cy];
		cx += dx, cy += dy;
	}
	cx = x, cy = y;
	FU(i,n){
		a[cx][cy] = b[s+i];
		cx += dx, cy += dy;
	}
}

void reval(int n,int (*a)[N]){
	FU(i,n) FU(j,n){
		printf("%d",a[i][j]);
		if(i==n-1 && j==n-1) putchar('\n');
		else putchar(' ');
	}
}

void init(int n,int (*a)[N]){
	int k = 1;
	FU(i,n) FU(j,n) a[i][j] = k++;
}

int main()
{
	int ca,n,m,x,s,a[N][N];
	char op;
	scanf("%d",&ca);
	while(ca--){
		scanf("%d %d",&n,&m);
		init(n,a);
		FU(i,m){
			scanf(" %c %d %d",&op,&x,&s);
			x--;
			switch(op){
				case 'L': shift(n,a,x,0,0,1,s); 		break;
				case 'R': shift(n,a,x,0,0,1,n-s);	 	break;
				case 'U': shift(n,a,0,x,1,0,s);			break;
				case 'D': shift(n,a,0,x,1,0,n-s);		break;
			}					
		}
		reval(n,a);
	}
	return 0;
}

你可能感兴趣的:(#,128,模拟考试)