丝雨学姐小灶班——Week 5
听说我已经进入NOJ的水题区了呢
/斜眼笑/斜眼笑/斜眼笑
- 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;
}
- 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;
}
模拟竖式做除法的步骤,我迷醉了~
还有噢,最后一位要拿出来单独进行四舍五入的处理的,不能囫囵着就跟着前面一起输出了呀!
- NOJ 37# 函数模板
狗屎一般的 cin 输入
很好,你赢了,我TM记住你了,MMP!!!
- 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;
}
- NOJ 41、42# 左上角左下角右上角右下角
反对角线
if (i>=(n-j-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;}}
}
- 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啦,那题目就可以做了呢~
- NOJ 51# 字符串逆序
一边读入一边判断字符
char s[100];while ((s[cnt]=cin.get()) != ‘ ’) {cnt++;}
- NOJ 53# 字符串排序
#include <string.h>
……
strcmp(a,b); //判断两字符串大小
strcpy(a,b); //将字符串b的内容复制入字符串a中
希望写个排序的函数然后在main里调用呢,没成功,貌似是因为二维数组参数传不进去?不明白呀不明白……
- 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辣鸡呢~
- NOJ 57# 字符串替换
巧做标记,输出时剔除多余空格即可
- NOJ 58# 文章统计
初试指针,真他娘的爽!!!
写了个计数函数,从函数里直接更改main里cnt的值,三个字符串分别调用三次函数就完事儿了,so easy!
- 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;
}
丝雨学姐小灶班——Week 5相关推荐
- 丝雨学姐小灶班——Week7
NOJ 71# 大数加法 我死了... #include <stdio.h> #include <stdlib.h> #include <string.h>void ...
- 丝雨学姐小灶班——Week 2
P1085 不高兴的津津 这题让我发现了一个神奇的东西--break.原来还有跳出循环这种操作的2333. 这题大体上还是好理解的,正好试着把 Week 1 里自己瞎捣鼓的数组用了一下(后来发现就是多 ...
- 丝雨学姐小灶班——Week 3
国庆假期首尾抢刷NOJ 2333 保留小数位数 double a,b,c;scanf("%lf %lf %lf",&a,&b,&c);printf(&quo ...
- 丝雨学姐小灶班——Week 1
The Story is Just Beginning P1000 超级玛丽游戏 用"xxx\n"分别输出各行内容即可 P1001 A+B Problem Hello, World ...
- 丝雨学姐小灶班——Week 6
NOJ 61# 源程序添加行号 卡了足足一个星期才开始做文件这一季的题目,真的是心累 直接上新学到的函数: FILE * fopen(const char * path,const char * mo ...
- 丝雨学姐小灶班——Week 4
NOJ 27# 粒子裂变 不用递归即可解决:用中间变量暂时储存上一时刻的数据:各步骤之间的逻辑关系 #include <iostream> using namespace std;int ...
- 辽大 计算机二级培训,辽宁大学-中软国际校企合作班 学长学姐对你说~第二弹...
辽宁大学与中软国际有着10余年的校企合作经历.每一年通过辽宁大学-中软国际校企合作班联合培养后,就业入职各大IT企业的学生数量,都在不断的增加.上一次学长学姐对你说,让学弟学妹们对于我们辽宁大学-中软 ...
- 考研复试班学姐揭秘考研复试中导师最爱问的问题
原文链接// https://tm.qiaoqiaoxue.cn/article/105 1.请您做一个简单的自我介绍 并且在介绍自己之前一定要做好充分的准备,因为您的经历比您的名字更重要.最重要的是 ...
- 5分绩点转4分_作为一名大学生,如何规划4年大学生活?学姐:建议从这5点做起...
导语:作为一名大学生,如何规划4年大学生活?学姐:建议从这5点做起 进入大学后,同学们会拥有更多可自由支配的时间.大学课余时间多,家长不在身边,老师又不管.同学们可以说是彻底自由了.但是世界上没有绝对 ...
最新文章
- Router OS之禁止P2P下载
- 经典面试题:在这个场景下,你怎么进行性能调优?
- 高并发负载均衡(三):LVS的DR模型试验搭建
- 从零开始学_JavaScript_系列(四)——jquery(基础,选择器,触发条件,动画,回调函数)...
- 完美运营牛帮任务平台源码 仿悬赏猫支持封装APP
- java工商银行项目_ChaosBlade 在工商银行混沌工程体系中的应用实践
- 路飞学城-Python爬虫集训-第一章
- 中国水上健身器材市场趋势报告、技术动态创新及市场预测
- GNS3环境安装流程
- 00、Python源码编译
- arduino蓝牙通讯代码_arduino笔记二:arduino与手机蓝牙通讯
- matlab写子函数,matlab主函数子函数怎么写
- 因果推断学习笔记三——Uplift模型
- JavaScript 编写Date 格式化方法『Python风格』
- Power BI中突出显示矩阵的最大值与最小值
- Windows编程——读写锁
- MA5680T降级操作及注意事项
- 微信小程序图片(单图多图上传显示)
- Manjaro、ArchLinux 网易云音乐无法启动修复记录
- 什么是闭包,闭包的作用与好处是什么,何时使用闭包,对闭包的改进