丝雨学姐小灶班——Week 5

听说我已经进入NOJ的水题区了呢

/斜眼笑/斜眼笑/斜眼笑

  1. NOJ 26# 羊羊聚会

扩展欧几里得问题………… /挠头
先上一段欧几里得问题的证明:

gcd(a,b) = gcd(b,a mod b) (不妨设a>b 且r=a mod b ,r不为0)
证法一
a可以表示成a = kb + r(a,b,k,r皆为正整数,且r<b),则r = a mod b
假设d是a,b的一个公约数,记作d|a,d|b,即a和b都可以被d整除。
而r = a - kb,两边同时除以d,r/d=a/d-kb/d=m,由等式右边可知m为整数,因此d|r
因此d也是b,a mod b的公约数
假设d是b,a mod b的公约数, 则d|b,d|(a-k*b),k是一个整数。
进而d|a.因此d也是a,b的公约数
因此(a,b)和(b,a mod b)的公约数是一样的,其最大公约数也必然相等,得证。
证法二
第一步:令c=gcd(a,b),则设a=mc,b=nc
第二步:可知r =a-kb=mc-knc=(m-kn)c
第三步:根据第二步结果可知c也是r的因数
第四步:可以断定m-kn与n互素【否则,可设m-kn=xd,n=yd,(d>1),则m=kn+xd=kyd+xd=(ky+x)d,则a=mc=(ky+x)dc,b=nc=ycd,故a与b最大公约数≥cd,而非c,与前面结论矛盾】
从而可知gcd(b,r)=c,继而gcd(a,b)=gcd(b,r),得证
注意:两种方法是有区别的。

扩展欧几里得算法

对于不完全为 0 的非负整数 a,b,gcd(a,b)表示 a,b 的最大公约数,必然
存在整数对 x,y ,使得 gcd(a,b)=ax+by。
求解 x,y的方法的理解
设 a>b。
① 显然当 b=0 时,gcd(a,b)=a。此时 x=1,y=0;
② 当 a>b>0 时,
设 ax1+ by1= gcd(a,b);
bx2+ (a mod b)y2= gcd(b,a mod b);
根据朴素的欧几里德原理有 gcd(a,b) = gcd(b,a mod b);
则:ax1+ by1= bx2+ (a mod b)y2;
即:ax1+ by1= bx2+ (a - [a / b] * b)y2=ay2+ bx2- [a / b] * by2;
说明: a-[a/b]*b即为mod运算。[a/b]代表取小于a/b的最大整数。
也就是ax1+ by1 == ay2+ b(x2- [a / b] *y2);
根据恒等定理得:x1=y2; y1=x2- [a / b] *y2;
这样我们就得到了求解 x1,y1 的方法:x1,y1 的值基于 x2,y2.
上面的思想是以递归定义的,因为 gcd 不断的递归求解一定会有个时候 b=0,所以递归可以结束。

题解题解
https://blog.csdn.net/k183000860/article/details/50211715
原来NOJ就是把POJ的P改成N再把青蛙改成美羊羊沸羊羊做出来的呀 /撑脸
附上代码:

#include <iostream>
#include <stdio.h>
using namespace std;

long long gcd(long long a,long long b,long long &x,long long &y)
{
	if(b == 0)
	{
		x = 1;
		y = 0;
		return a;
	}
	long long r = gcd(b,a%b,x,y);	//递归咋整的还是得好好理解理解
	long long temp = x;
	x = y;
	y = temp - a/b*y;
	return r;
}

int main()
{
	long long x,y,m,n,l,p,q;
	scanf("%lld %lld %lld %lld %lld",&x,&y,&m,&n,&l);
	int r = gcd(n-m,l,p,q);
	if((x-y)%r)
		cout<<"Impossible";
	else
	{
		long long d = l/r,dd = (x-y)/r;
		p *= dd;
		p = (p%d+d)%d;
		printf("%lld\n",p);
	}
	return 0;
}
  1. NOJ 30# 分数化小数

乍一看题目是很2呢,和第一眼看“1”的传奇的感觉一样emmm
但是这里保留小数的位数是一个读入的变量呢!更何况这个变量的范围还是<=100……
我联想到在书上64页看到过手写保留小数位数的操作,就拿pow函数来试一试咯,还得结合网上找来的闻所未闻的 %g 输出(浮点数不显无意义的零"0")(woc可以把小数部分末尾的0都去掉,好NB啊)。本地运行感觉完全OK,但是贴上去是PE…ε=(´ο`*)))唉,心累
一看题解……原来用自带除法进行计算,数据的精度始终是无法达到要求的,只能自己自己手写模拟除法的过程么……怪不得呢,我就说怎么会在第30题突然来了道水题 /笑哭
附上原来的代码(后来证实最多只能保留六位小数):

#include <stdio.h>
#include <cmath>
#include <iostream>
using namespace std;

int main()
{
    int a,b,c;
    double ret;
    cin>>a>>b>>c;
    ret=(double)a/(double)b;
    ret*=pow(10,c);
    ret=round(ret)/pow(10,c);
    printf("%g",ret);

    return 0;
}

然后在找题解的过程中发现了printf的神奇用法:

printf("%*.*lf",c+1,c,(double)a/b);	//输出c+1个字宽保留c位小数的浮点数运算结果
printf("%*s%s%*s",5,"","123",3,"" );	//输出5个空格,输出123,输出3个空格

printf中%后面的*号是用来表示宽度,具体的宽度由后面的变量来决定
比如
printf( “%*d”, 5,i);

printf( “%5d”,i);
或者
j=5;
printf( “%*d”, j, i );
是等价的
%5d的意思就是输出宽度为5的整数,如果不足5位,则在左边补空格
%-5d则是在右边补空格
%05d则是在左边补零

最后,老老实实手写除法:

#include <stdio.h>

int main()
{
    int a,b,c,i;
    scanf("%d %d %d",&a,&b,&c);
    printf("%d.",a/b);
    for (i=1; i<c; i++) {
        a=(a%b)*10;
        printf("%d", a/b);
    }
    a=(a%b)*10;
    if ((a%b)*10/b >= 5) printf("%d", a/b+1);
    else printf("%d", a/b);

    return 0;
}

模拟竖式做除法的步骤,我迷醉了~
还有噢,最后一位要拿出来单独进行四舍五入的处理的,不能囫囵着就跟着前面一起输出了呀!

  1. NOJ 37# 函数模板

狗屎一般的 cin 输入
很好,你赢了,我TM记住你了,MMP!!!

  1. NOJ 40# 循环移位

不好意思我完全不懂

#include <iostream>
using namespace std;

unsigned rol(unsigned val, int size)	//循环左移
{
    unsigned res = val << size;
    res |= val >> (32 - size);
    return res;
}

unsigned ror(unsigned val, int size)	//循环右移
{
    unsigned res = val >> size;
    res |= val << (32 - size);
    return res;
}

int main()
{
    int value,n;
    cin>>value>>n;
    if (n>0) cout<<ror(value,n)<<endl;
    else cout<<rol(value,-n)<<endl;
    return 0;
}
  1. NOJ 41、42# 左上角左下角右上角右下角

反对角线

if (i>=(n-j-1)) {
  1. NOJ 44# 选择排序

排从第s个开始的连续m个元素,应该挺基础的吧,直接上代码:

void SelectionSort(int a[],int s,int m)
{
    int i,j;
    for (i=s; i<s+m; i++) {
        int t=i;
        for (j=i+1; j<s+m; j++) {
            if (a[j]>a[t]) t=j;
        }
        {
            int temp=a[i];
            a[i]=a[t];
            a[t]=temp;
        }
    }
}
  1. NOJ 43# 山迪的麻烦

看到有人说是冒泡排序……好吧我来学习一下:

冒泡排序(Bubble Sort),它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。
这个算法的名字由来是因为越大的元素会经由交换慢慢“浮”到数列的顶端,所以叫“冒泡排序”。
原理
冒泡排序算法的原理如下:
比较相邻的元素。如果第一个比第二个大,就交换他们两个。
对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
针对所有的元素重复以上的步骤,除了最后一个。
持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

#include <iostream>
using namespace std;
template<typename T>
//整数或浮点数皆可使用
void bubble_sort(T arr[], int len)
{
    int i, j;  T temp;
    for (i = 0; i < len - 1; i++)
        for (j = 0; j < len - 1 - i; j++)
        if (arr[j] > arr[j + 1])
        {
            temp = arr[j];
            arr[j] = arr[j + 1];
            arr[j + 1] = temp;
        }
}
int main()
{
    int arr[] = { 61, 17, 29, 22, 34, 60, 72, 21, 50, 1, 62 };
    int len = (int) sizeof(arr) / sizeof(*arr);
    bubble_sort(arr, len);
    for (int i = 0; i < len; i++)
        cout << arr[i] << ' ';
 
    cout << endl;
 
    float arrf[] = { 17.5, 19.1, 0.6, 1.9, 10.5, 12.4, 3.8, 19.7, 1.5, 25.4, 28.6, 4.4, 23.8, 5.4 };
    len = (int) sizeof(arrf) / sizeof(*arrf);
    bubble_sort(arrf, len);
    for (int i = 0; i < len; i++)
        cout << arrf[i] << ' ';
 
    return 0;
}

OK啦,那题目就可以做了呢~

  1. NOJ 51# 字符串逆序

一边读入一边判断字符

char s[100];
    while ((s[cnt]=cin.get()) != ‘ ’) {
        cnt++;
    }
  1. NOJ 53# 字符串排序
#include <string.h>
……
strcmp(a,b);	//判断两字符串大小
strcpy(a,b);	//将字符串b的内容复制入字符串a中

希望写个排序的函数然后在main里调用呢,没成功,貌似是因为二维数组参数传不进去?不明白呀不明白……

  1. NOJ 55# 字符串取整数

这题做得我一个头四个大 /托腮
主要问题是最后为啥二位数组里会被多写一遍第一行连续的整数呢?!真的好诡异啊!
最后只能开挂从后往前删掉这一行了 /摊手
好吧这个问题不管,审题才是最关键的好吗 /笑哭
“连续”表意不明呀,但是WA以后我就应该机灵一点考虑单独一个‘1’这种是不是也是题目希望我考虑进去的呀
最后用我最喜欢的暴力无脑 if 讨论法把中间重写了一遍,AC啦,完全没问题
另外请欣赏胡大佬的杰作:

#include <stdio.h>
#include <string.h>

int main(void){
	char string[1024], ch;
	int num[256], i = 0;
	while((ch = getchar()) != '\n'){
		string[i++] = ch;
	}
	int len = strlen(string);
	int if_n = 0, count = -1, if_l = 0;
	for(i = 0; i < len; i++){
		if(string[i] > 47 && string[i] < 58) if_n = 1;
		else if_n = 0;
		if(!if_l && if_n){
			//if(~count) num[count] /= 10;
			num[++count] = 0;
			num[count] += string[i] - 48;
		}
		else if(if_l && if_n){
			num[count] *= 10;
			num[count] += string[i] - 48;
		}
		else{

		}
		if_l = if_n;
	}
	printf("%d\n",++count);
	for(i = 0; i < count; i++){
		if(i) printf(" ");
		printf("%d",num[i]);
	}
	return 0;
}

看来我麻里麻烦整了一个二维数组也是真TM辣鸡呢~

  1. NOJ 57# 字符串替换

巧做标记,输出时剔除多余空格即可

  1. NOJ 58# 文章统计

初试指针,真他娘的爽!!!
写了个计数函数,从函数里直接更改main里cnt的值,三个字符串分别调用三次函数就完事儿了,so easy!

  1. NOJ 59# Coin Test

翻了一下之前的gcd函数写了一个更相减损法求最大公约数来约分的函数gcdyf:

void gcdyf(int *a,int *b)
{
    int temp_a=*a,temp_b=*b;
    while (temp_a!=temp_b) {
    if (temp_a>temp_b) temp_a -= temp_b;
    else temp_b -= temp_a;}
    int gcd=temp_b;
    *a/=gcd;
    *b/=gcd;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
西北工业大学NOJC程序设计习题答案(非本人制作,侵删) 1.“1“的传奇 2.A+B 3.A+BⅡ 4.AB 5.ACKERMAN 6.Arithmetic Progressions 7.Bee 8.Checksum algorithm 9.Coin Test 10.Dexter need help 11.Double 12.Easy problem 13.Favorite number 14.Graveyard 15.Hailstone 16.Hanoi Ⅱ 17.Houseboat 18.Music Composer 19.Redistribute wealth 20.Road trip 21.Scoring 22.Specialized Numbers 23.Sticks 24.Sum of Consecutive 25.Symmetric Sort 26.The Clock 27.The Ratio of gainers to losers 28.VOL大学乒乓球比赛 29.毕业设计论文打印 30.边沿与内芯的差 31.不会吧,又是A+B 32.不屈的小蜗 33.操场训练 34.插入链表节点 35.插入排序 36.插入字符 37.成绩表计算 38.成绩转换 39.出租车费 40.除法 41.创建与遍历职工链表 42.大数乘法 43.大数除法 44.大数加法 45.单词频次 46.迭代求根 47.多项式的猜想 48.二分查找 49.二分求根 50.发工资的日子 51.方差 52.分离单词 53.分数拆分 54.分数化小数 55.分数加减法 56.复数 57.高低交换 58.公园喷水器 59.韩信点兵 60.行程编码压缩算法 61.合并字符串 62.猴子分桃 63.火车站 64.获取指定二进制位 65.积分计算 66.级数和 67.计算A+B 68.计算PI 69.计算π 70.计算成绩 71.计算完全数 72.检测位图长宽 73.检查图像文件格式 74.奖金发放 75.阶乘合计 76.解不等式 77.精确幂乘 78.恐怖水母 79.快速排序 80.粒子裂变 81.链表动态增长或缩短 82.链表节点删除 83.两个整数之间所有的素数 84.路痴 85.冒泡排序 86.你会存钱吗 87.逆序整数 88.排列 89.排列分析 90.平均值函数 91.奇特的分数数列 92.求建筑高度 93.区间内素数 94.三点顺序 95.山迪的麻烦 96.删除字符 97.是该年的第几天 98.是该年的第几天? 99.数据加密 100.搜索字符 101.所有素数 102.探索合数世纪 103.特殊要求的字符串 104.特殊整数 105.完全数 106.王的对抗 107.危险的组合 108.文件比较 109.文章统计 110.五猴分桃 111.小型数据库 112.幸运儿 113.幸运数字”7“ 114.选择排序 115.寻找规律 116.循环移位 117.延伸的卡片 118.羊羊聚会 119.一维数组”赋值“ 120.一维数组”加法“ 121.勇闯天涯 122.右上角 123.右下角 124.圆及圆球等的相关计算 125.圆及圆球等相关计算 126.程序员添加行号 127.找出数字 128.找幸运数 129.找最大数 130.整数位数 131.重组字符串 132.子序列的和 133.子字符串替换 134.自然数立方的乐趣 135.字符串比较 136.字符串复制 137.字符串加密编码 138.字符串逆序 139.字符串排序 140.字符串替换 141.字符串左中右 142.组合数 143.最次方数 144.最大乘积 145.最大整数 146.最小整数 147.最长回文子串 148.左上角 149.左下角

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值