[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-OZFY1w5J-1597297949257)(D:\Software\typora\Picture\image-20200729155404399.png)]
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-lDdzCr9F-1597297949260)(D:\Software\typora\Picture\image-20200803154949702.png)]
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-VlEBZaLN-1597297949261)(D:\Software\typora\Picture\image-20200803161202085.png)]
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-EIE2axWJ-1597297949263)(D:\Software\typora\Picture\image-20200803161734085.png)]
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-qMSTYvlV-1597297949265)(D:\Software\typora\Picture\image-20200803161803680.png)]
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-iSXjuBWm-1597297949266)(D:\Software\typora\Picture\image-20200803161836316.png)]
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-yRL72oAJ-1597297949267)(D:\Software\typora\Picture\image-20200803161902113.png)]
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-J0v3bOGw-1597297949268)(D:\Software\typora\Picture\image-20200803164910263.png)]
原型中:
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-OvC6YtPn-1597297949269)(D:\Software\typora\Picture\image-20200805165419239.png)]
和printf類似
scanf的返回值範圍是從0開始,-1是第一個非法返回值
EOF:End Of File的縮寫,通常在文字的最後存在此字元表示資料結束,其值通常爲-1,常用做法
while(scanf("%d",&n) != EOF)
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-3OsW87BO-1597297949270)(D:\Software\typora\Picture\image-20200805170516083.png)]
#include<stdio.h>
int main() {
int n;
while (scanf("%d", &n) != EOF) {
printf(" has %d digits!\n", printf("%d", n));
}
return 0;
}
例:
輸入:123
輸出:123 has 3 digits!
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-UudC7C2x-1597297949270)(D:\Software\typora\Picture\image-20200805170915275.png)]
#include<stdio.h>
int main() {
char a[1000] = {0};
while (scanf("%[^\n]s", a) != EOF) {
getchar();
printf(" has %d chars!\n", printf("%s", a));
}
return 0;
}
例:
輸入:hello world
輸出:hello world has 11 chars!
其中scanf中「[]」是正則表達式字元匹配集,例如括號裏面是a~z,那麼只會讀入範圍裏面的字元,遇到不是的就會停止,^是取反,也就是說除了\n以外的都可以讀入;
./a.out > out叫做輸出重定向,執行的輸出結果到out這個檔案
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-sAHwp4VX-1597297949271)(D:\Software\typora\Picture\image-20200805203416140.png)]
按此程式執行,會輸出一大串
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-jINDXbFk-1597297949272)(D:\Software\typora\Picture\image-20200805203555101.png)]
只有第一次讀入了,後面是因爲第一次讀入完成後指針指向了\n,第二次的時候判定爲scanf返回值爲0,並不是-1,所以還會不斷的列印,造成死回圈
#include <stdio.h>
int main() {
int n;
scanf("%d", &n); //stdin標準輸入
printf("%d\n",n); //stdout標準輸出
char str[100] = "hello world"; //字串輸入
printf("%s\n", str); // 字串輸出
return 0;
}
#include <stdio.h>
int main() {
int n;
str ch[5];
scanf("%d%s", &n, &ch[0]);
printf("n = %d, ch = %s", n, ch[0]);
return 0;
}
字串,可以以陣列的形式輸入;還有%s的用法
s可以理解爲string,是將輸出列印到陣列當中去
#include <stdio.h>
int main() {
char str[100] = {0};
sprintf(str, "%d.%d.%d.%d", 192, 168, 1, 10);//輸出到str陣列
printf("str = %s\n", str);//列印str陣列
return 0;
}
輸出:str = 192.168.1.10
2.rwx(000~111),分別代表可讀,可寫,可執行,輸入一個數字判斷它的許可權,可讀的話加一個「()」,可寫的話加一個「[]」,可執行的話」{}「。
#include <stdio.h>
#define swap(a, b) {\
__typeof(a) __temp = a;\
a = b; b = __temp;\
}
int main() {
char str[100] = {0}, buffer[100] = {0}, *p = str, *q = buffer;
sprintf(str, "%d.%d.%d.%d", 192, 168, 1, 10);
if (n & 1) {
sprintf(q, "%s", p);
swap(q, p);
}
if (n & 2) {
sprintf(q, "[%s]", p);
swap(q, p);
}
if (n & 4) {
sprintf(q, "{%s}", p);
swap(q, p);
}
printf("%s\n", p);
return 0;
}
sprintf(str, "(%s)", str);//會出現錯誤,原因是str邊列印邊覆蓋
輸入:1;輸出:(192.168.1.10);
輸入:3;輸出:[(192.168.1.10)];
輸入:7;輸出:{[(192.168.1.10)]};
f可以理解爲file,將輸出列印到檔案當中去
#include <stdio.h>
int main() {
int n;
scanf("%d", &n);
FILE *fout = fopen("./output", "w");//結果輸出到output檔案中,w代表以寫的方式
fprintf(stdout, "%s\n", p);
return 0;
}
這三個printf家族:三者的返回值,及格式是相同的
分別是標準輸入,標準輸出,標準錯誤輸出,輸出會展現在終端上,在輸出重定向的時候(>),stderr的值不會出現在檔案中,只會出現在終端上,而stdout可以。
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-TRvQG5Hd-1597297949272)(D:\Software\typora\Picture\image-20200807133651461.png)]
逆運算是一種對應法則。假設A是一個非空集合,對A中的任意兩個元素a和b,根據某種法則使A中有唯一確定的元素c與它們對應,我們就說這個法則是A中的一種運算。反過來,如果已知元素c,以及元素a、b中的一個,按照某種法則,可以得到另一個元素,這樣的法則也定義了一種運算,這樣的運算叫做原來運算的逆運算。
如減法是加法的逆運算。a + b = c,那麼 c - a = b, c - b = a.
&與;|或;^互斥或(是本身的逆運算);~按位元取反;
例:~6 = -7;~(-6) = 5;正數儲存爲原碼,負數儲存爲二補數;
<<左移:補0,相當於*2;>>右移:高位補符號位(與原數正負一致),相當於/2;
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-f4b812b7-1597297949273)(D:\Software\typora\Picture\image-20200807135905021.png)]
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-AH4x8548-1597297949274)(D:\Software\typora\Picture\image-20200807150751172.png)]
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-MSkEiXfm-1597297949275)(D:\Software\typora\Picture\image-20200807151211644.png)]
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-fISSnHFp-1597297949275)(D:\Software\typora\Picture\image-20200807151249492.png)]
也可叫」天花板「函數
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-10nieN4B-1597297949276)(D:\Software\typora\Picture\image-20200807151423371.png)]
也叫」地板「函數
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-bWcojYro-1597297949276)(D:\Software\typora\Picture\image-20200807151823022.png)]
注意:標頭檔案爲<stdlib.h>
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-1ElgzQFb-1597297949277)(D:\Software\typora\Picture\image-20200807152245400.png)]
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-T24CrM93-1597297949278)(D:\Software\typora\Picture\image-20200807152317558.png)]
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-NLdPCUDo-1597297949279)(D:\Software\typora\Picture\image-20200807152345756.png)]
換底公式:
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-IhtH3VoS-1597297949280)(D:\Software\typora\Picture\image-20200807161734465.png)]
注意:x是弧度值,
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-5brTyoFg-1597297949280)(D:\Software\typora\Picture\image-20200807162203166.png)]
#include <stdio.h>
#include <math.h>
int main() {
double x;
scanf("%f", &x);
printf("%f\n", pow(x, 1.0/3.0));
return 0;
}
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-kkBXKMTM-1597297949281)(D:\Software\typora\Picture\image-20200807162741786.png)]
#include <stdio.h>
#include <math.h>
#define PI acos(-1)
int main() {
double x;
scanf("%f", &x);
printf("%lf", PI / 180.0 * x);
return 0;
}
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-ue8lRyGE-1597297949282)(D:\Software\typora\Picture\image-20200807163017323.png)]
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-Ffs4ao88-1597297949283)(D:\Software\typora\Picture\image-20200807163109269.png)]
#include <stdio.h>
int main() {
int a, b;
while (scanf("%d%d", &a, &b) != EOF) {
printf("%d\n", a + b);
}
return 0;
}
輸入:2 3;輸出:5
其中,
while (scanf("%d%d", &a, &b) != EOF)
可替換成
while (~scanf("%d%d", &a, &b))
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-nqZ9jS72-1597297949283)(D:\Software\typora\Picture\image-20200807170629595.png)]
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-lu9XBIxC-1597297949284)(D:\Software\typora\Picture\image-20200807170648030.png)]
通過交換兩個地址完成交換
#include <stdio.h>
int main() {
int a, b;
while (~scanf("%d%d", &a, &b)) {
int *p = &a;
(*p)--;
printf("a = %d, b = %d\n", a, b);
a ^= b;
b ^= a;
a ^= b;
printf("swap : a = %d, b = %d\n", a, b);
}
return 0;
}
#include <stdio.h>
int rev(int n) {
int sum = 0;
while (n) {
sum = sum * 10 + n % 10;
n /= 10;
}
return sum;
}
int main() {
int n;
while (scanf("%d", &n) != EOF) {
printf("%d\n", rev(n));
}
return 0;
}
輸入:123;輸出:321
C語言支援bool型別,標頭檔案爲<stdbool.h>
#include <stdio.h>
#include <stdbool.h>
int main(void) {
bool a=true, b=false;
printf("%d\n", a&&b);
printf("%d\n", a||b);
printf("%d\n", !b);
}
輸出:0 1 1
例如,int32_t,32表示32位元 = 4位元組,表示定義的整型變數佔空間大小爲4個位元組,能表示的最大整數爲2的31次方;
uint32_t,爲無符號整型,能表示大的最大整數爲2的32次方;
例如:INT32_MIN/INT32_MAX是一個宏,前者表示32位元表示的最小值,後者表示32位元的最大值
#include <stdio.h>
#include <inttypes.h>
int main() {
int32_t a = 123;
int64_t b = 256;
int8_t c = 123;
printf("a = %lu, b = %lu\n", sizeof(a), sizeof(b));//a=4,b=8
printf("c = %" PRId8 "\n", c); //123
printf("sizeof(c) = %" PRIu64 "\n", sizeof(c));//1
printf("INT32_MIN = %d\n", INT32_MIN);//-2147483648
printf("INT32_MAX = %d\n", INT32_MAX);//2147483647
printf("INT16_MIN = %d\n", INT16_MIN);//-32768
printf("INT16_MAX = %d\n", INT16_MAX);//32767
printf("INT8_MIN = %d\n", INT8_MIN);//-128
printf("INT8_MAX = %d\n", INT8_MAX);//127
printf("PRId64 = %s\n", PRId64);//ld
printf("PRId32 = %s\n", PRId32);//d
printf("PRId16 = %s\n", PRId16);//d
return 0;
}
PRIdx:也是一個宏,例PRId8,會自動匹配變數的型別
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-r0dCZdy7-1597297949285)(D:\Software\typora\Picture\image-20200809200111653.png)]
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-Oex2N5Yg-1597297949286)(D:\Software\typora\Picture\image-20200809200156843.png)]
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-1LPnFYWn-1597297949286)(D:\Software\typora\Picture\image-20200809132738849.png)]
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-kHWWnPak-1597297949287)(D:\Software\typora\Picture\image-20200809115100150.png)]
返回值:true / false,即1 / 0;
!!(x) :歸一化,例如x = 5,結果爲1;x = 0,結果爲0;
三種結構:順序,分支或選擇,回圈;
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-DBJQKxOd-1597297949288)(D:\Software\typora\Picture\image-20200809123446334.png)]
還有,if (表達式) 程式碼塊;
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-cvxSoeI7-1597297949293)(D:\Software\typora\Picture\image-20200809123840152.png)]
#include <stdio.h>
int main() {
int n;
scanf("%d", &n);
if (!n) {
printf("FOOLISH\n");
} else if (n < 60) {
printf("FAIL\n");
} else if (n < 75) {
printf("MEDIUM\n");
} else if (n <= 100) {
printf("GOOD\n");
}
return 0;
}
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-WAr9wlM1-1597297949294)(D:\Software\typora\Picture\image-20200809124420904.png)]
還有,default: 程式碼塊;break;
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-eGp2iRZ9-1597297949294)(D:\Software\typora\Picture\image-20200809124827946.png)]
#include <stdio.h>
int main() {
int n;
scanf("%d", &n);
switch(n) {
case 1:
printf("one\n");
break;
case 2:
printf("two\n");
break;
case 3:
printf("three\n");
break;
default :
printf("ERROR\n");
}
return 0;
}
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-mYfd6XM1-1597297949296)(D:\Software\typora\Picture\image-20200809125209305.png)]
#include <stdio.h>
int main() {
int n;
scanf("%d", &n);
switch (n) {
case 1:
printf("one ");
case 2:
printf("two ");
case 3:
printf("three\n");
break;
default :
printf("error\n");
break;
}
return 0;
}
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-jDjhJ2iz-1597297949296)(D:\Software\typora\Picture\image-20200809125809235.png)]
bool isPalindrome(int x) {
if (__builtin_expect(!!(x < 0), 0)) return false;//首先排除掉x<0
int y = 0, z = x;
while (x) {
y = y * 10 + x % 10;
x /= 10;
}
return z == y;
}
__builtin_expect是一個宏,判斷x < 0 這種情況是經常成立還是不成立的,後面第二個0,是代表不經常成立,這就是分支預測;
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-vmPsM1EA-1597297949297)(D:\Software\typora\Picture\image-20200809131221932.png)]
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-rIkSLSDc-1597297949297)(D:\Software\typora\Picture\image-20200809130335828.png)]
分析程式執行方式(CPU):
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-KkLBLbbV-1597297949298)(D:\Software\typora\Picture\image-20200809130418594.png)]
執行速度:外存 < 記憶體 < 快取 < CPU;序列計算 < 並行計算;
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-EQrSNeaJ-1597297949299)(D:\Software\typora\Picture\image-20200809131729729.png)]
可以幫助CPU做分支預測;
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-v36lGD1Z-1597297949299)(D:\Software\typora\Picture\image-20200809132103330.png)]
#include <stdio.h>
int main() {
int n = 1;
while (n < 101) {
printf("%d\n", n);
n ++;
}
return 0;
}
#include <stdio.h>
int main() {
int n = 1;
do {
printf("%d\n", n);
n ++;
} while (n <= 100);
return 0;
}
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-6CA0mr4m-1597297949300)(D:\Software\typora\Picture\image-20200809132600291.png)]
也可以,初始化部分爲空;
#include <stdio.h>
int main() {
int n;
for (n = 1; n < 101; n++) {
printf("%d\n", n);
}
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
int a = 0, b = 0;
if ((a++) && (b++)) {
printf("true\n");
} else {
printf("false\n");
}
//輸出:false,a++是先用再加,&&運算子是前面不符合就不判斷後面了,直接下一步
printf("test1 : a = %d, b = %d\n", a, b);
//輸出:a = 1, b = 0
if ((a++) || (b++)) {
printf("true\n");
} else {
printf("false\n");
}
//輸出:true
printf("test2 : a = %d, b = %d\n", a, b);
//輸出:a= 2, b = 0
int n, cnt = 0;
scanf("%d", &n);
srand(time(0));//隨機種子,標頭檔案<stdlib.h>,種子爲時間
//time(0)是返回當前的系統時間
//判斷奇偶
if (n & 1) {
printf("%d is a odd!\n", n);
} else {
printf("%d is a even!\n", n);
}
//0~100亂數
for (int i = 0; i < n; i++) {
int val = rand() % 100;
i && printf(" ");//如果不是第一個數就可以有空格
//也可以 i && printf(" "); 或者 i = 0 || printf(" ");
printf("%d", val);
cnt += (val & 1);//判斷奇數有幾個
}
printf("\n");
printf("odd nums : %d\n", cnt);//輸出奇數有幾個
//判斷數位的位數
int x, digits = 0;
scanf("%d", &x);
do {
digits++;
x /= 10;
} while (x); //可以包括0值
printf("digits : %d\n", digits);
return 0;
}
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-55h2oO0I-1597297949300)(D:\Software\typora\Picture\image-20200809205124489.png)]
有函數的,可讀性更高,更容易偵錯
功能:判斷素數; 整體程式碼塊是函數的定義
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-oRBPP95m-1597297949301)(D:\Software\typora\Picture\image-20200809205222562.png)]
返回值爲空時,可以用void;
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-cTKdyius-1597297949302)(D:\Software\typora\Picture\image-20200809210202077.png)]
比較古老,現在一般不這麼用
參數變數的型別放在了」()「外面;
返回值是給操作系統看的;命令:echo $,如果結果爲0,表示上一條命令執行成功;
遞推是一種演算法;遞回是自己呼叫自己;
可以用數學歸納法,理解遞回;
#include <stdio.h>
int fac(int n) {
if (n == 0) return 1; //邊界條件
return n * fac(n - 1); //遞回過程
}
int main() {
int n;
while (~scanf("%d", &n)) {
printf("fac(%d) = %d\n", n, fac(n));
}
return 0;
}
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-knwd8AAR-1597297949303)(D:\Software\typora\Picture\image-20200809213006681.png)]
把函數當作一個變數,傳進去;傳的是函數的地址;第一個int是函數的型別,第二個是函數的參數型別;最後的x是類似於分段函數的參數變數;
以歐拉計劃045題爲例;
程式 = 演算法 + 數據結構
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-4dWO8yBc-1597297949304)(D:\Software\typora\Picture\image-20200806141028654.png)]
求兩個數的最大公約數
首先先上結論,求最大公約數,我們可以通過遞回gcd(a,b)=gcd(b,a%b),gcd(a,0)=a計算,複雜度是log(n);
很明顯,這個偉大的結論gcd(a,b)=gcd(b,a%b),就是著名的歐幾裡得公式。
那麼怎麼證,其實還挺簡單的。我們把證明分爲兩步驟:
1、證明gcd(a,b)是b,a%b的一個公約數
2、證明這個公約數是最大的。
1、我們設gcd(a,b)=d,再令a=k1d,b=k2d.
我們再設,a=k*b+c(也就是a除以b商k餘c),那麼c就是餘數,也就是a%b.
講上面那個式子移項,得到c=a-k*b,然後再把a=k1*d,b=k2*d,這兩個式子裡的a、b帶入式子,得到:
c=k1*d-k*k2*d,在提取公因數d,得到c=(k1-k*k2)*d.這樣就說明,c,也就是a%b有d這個約數,因爲開始我們設b也有d這個約數,所以gcd(a,b)是b,a%b的一個公約數。
2、現在知道了它是一個公約數,那麼怎麼證它是最大的?(其實感性分析,a%b都變小了,公約數不可能更大呀!)
但是術學是一門嚴謹的學科,我們要嚴謹證明。我們知道,c(a%b)=(k1-kk2)d,b=k2d,我們只需要證明k1-kk2、k2互質就好了。
這裏可以用到反證法:我們假設k1-k*k2=q*t,k2=p*t,並且t>1(也就是那兩個不互質)。
我們將前面那個式子移項,得到k1=q*t+k*k2,再把這個k1代到最開始的a=k1*d,得到a=(q*t+k*k2)*d,再利用乘法分配律,得到:
a=q*t*d+k*k2*d,我們這時發現,k2*d不就是最開始的b嗎?,將其帶入,得到:a=q*t*d+b*d.
這時,我們再把k2=pt代入開始的b=k2d,得到b=ptd,再把這個式子代到a=qtd+bd.得到了:a=qtd+pt*d.提取公因數:a=(q+p)td
現在,再和b=ptd比較,發現他們的最大公因數變成了t*d和開始矛盾,所以假設不成立,反證成功!
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-6ixnWTDl-1597297949304)(D:\Software\typora\Picture\20190207101619404.jpg)]
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-d49MOzoN-1597297949305)(D:\Software\typora\Picture\image-20200810094554497.png)]
#include <stdio.h>
int gcd(int a, int b) {
return (b ? gcd(b, a % b) : a);//三目運算子b不爲0,執行gcd(b, a % b),否則執行a
}
int main() {
int a, b;
while (~scanf("%d%d", &a, &b)) {
printf("%d\n", gcd(a, b));
}
return 0;
}
求解a * x + b * y = 1 方程的一組整數解;是求解a * x + b * y = gcd(a, b);
先來看看一個重要的基本定理
裴蜀定理(貝祖定理)
對於整數a,b,他們關於x,y的線性不定方程ax+by=d,設gcd(a,b)=g,則可證明g|d,換句話說,就是g是a,b的最小線性組合。
證明:
設ax+by=d,g=gcd(a,b),設ax+by的最小值爲s,
∵ g|a,g|b
∴ g|d,g|s
設q=[as].則r=amods=a−q∗s=a−q∗(ax+by)=a(1−qx)+b(−qy)。
可見r也是x,y的線性組合,又r是s的餘數,r∈[0,s−1],又s是最小線性組合,∴r=0。
推出s|a,同理有s|b,則s|g,又已經有g|s,所以g=s。可知g是ax+by的最小線性組合。
推論:
a和b互質的充要條件是存在x,y使ax+by=1,因爲由上面的證明結論知道d(這裏是1)一定是gcd(a,b)的倍數。
其實還可以推廣到一堆數互質(這些數的gcd爲1)的情況。
拓展歐幾裡得
我們知道,一般的 歐幾裡得演算法是來求兩個數的最大公因數的,但是拓展歐幾裡得可以走得更遠,也就是說,它不僅僅求一個gcd,而是可以求出一些額外的東西。前面的定理說了a,b線性組合最小是gcd(a,b),我們就可以求出ax+by=gcd(a,b)對應的x,y出來。
怎麼求呢?我們已經知道當歐幾裡得演算法遞回到終點時,gcd(a,b)中的b已經是零,也就是說,這個時候a∗1+b∗0=a,x=1,y=0,我們就可以在這時反推上去求解最終的x,y
現在是遞回返回過程的某一步,我們已經求得了b和a%b的gcd,還有此時的x1,y1,就是說b∗x1+a%b∗y1=gcd,要怎麼求a,b的x,y呢?
我們知道a%b=a−[ab]∗b,gcd=b∗x1+(a−[ab]∗b)∗y1=b∗x1+a∗y1−[ab]∗y1∗b=a∗y1+(x1−[ab]∗y1)∗b=a∗x+b∗y
可以看出x=y1,y=x1−[ab]∗b.遞回返回時即可更新掉x,y的值返回即可。
#include <stdio.h>
int ex_gcd(int a, int b, int *x, int *y) {
if (!b) {
*x = 1, *y = 0;
return a;
}
int xx, yy, ret = ex_gcd(b, a % b, &xx, &yy);
*x = yy;
*y = xx - a / b * yy;
return ret;
}
int main() {
int a, b, x, y;
while (~scanf("%d%d", &a, &b)) {
printf("gcd(%d, %d) = %d\n", a, b, ex_gcd(a, b, &x, &y));
printf("%d * %d + %d * %d = %d\n", a, x, b, y, a * x + b * y);
}
return 0;
}
輸入:3 5;輸出:gcd(3, 5) = 1, 3 * 2 + 5 * -1 = 1;
輸入:2 4;輸出:gcd(2 ,4) = 2, 2 * 1 + 4 * 0 = 2;
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-ynI369C2-1597297949305)(D:\Software\typora\Picture\image-20200806164202851.png)]
實現找到最大值:
#include <stdio.h>
#include <stdarg.h>
int max_int(int n, ...) {
int ans = 0;
va_list arg;//將變參列表存到arg
va_start(arg, n);//定位到第一個參數位置
while (n--) {
int tmp = va_arg(arg, int);//arg中取int型別的變數
if (tmp > ans) ans = tmp;
}
va_end(arg);//結束
return ans;
}
int main() {
printf("%d\n", max_int(3, 1, 5, 3));
printf("%d\n", max_int(2, 1, 5));
printf("%d\n", max_int(6, 1, 5, 3, 18, 2, 9));
printf("%d\n", max_int(4, 1, 5, 3, 9, 18));//只會讀取前四個
return 0;
}
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-mIB0ypud-1597297949306)(D:\Software\typora\Picture\image-20200807111237828.png)]
方法一:利用回圈,挨個判斷
#include <stdio.h>
int is_val(int n) {
return n % 3 == 0 || n % 5 == 0;
}
int main() {
int sum = 0;
for (int i = 1; i < 1000; i++) {
if (is_val(i)) sum += i;
}
printf("%d\n", sum);
return 0;
}
這麼寫,時間複雜度爲O(n)
方法二:
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-lOTqzhJQ-1597297949306)(D:\Software\typora\Picture\image-20200807130102510.png)]
能被3或5整除的,可以用等差數列求和公式,相加,再減去公差爲15的等差數列求和,即爲答案,時間複雜度爲O(1)
#include <stdio.h>
int main() {
int sum3 = (3 + 999) * 333 / 2;
int sum5 = (5 + 995) * 199 / 2;
int sum15 = (15 + 999 / 15 * 15) * (999 / 15) / 2;
printf("%d\n", sum3 + sum5 - sum15);
return 0;
}
Answer:233168
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-apdCyABJ-1597297949307)(D:\Software\typora\Picture\image-20200809165117627.png)]
方法一:遍歷所有Fib(n),再找出偶數求和;
#include <stdio.h>
#define max_n 44
#define N 4000000
int fib[max_n + 5] = {1, 2, 0};//多加5位,防止不夠用
int main() {
int sum = 0;
for (int i = 2; i <= max_n; i++) {
fib[i] = fib[i - 1] + fib[i - 2];
}
for (int i = 0; i <= max_n; i++) {
if (fib[i] <= N && !(fib[i] & 1)) sum += fib[i];
}
printf("%d\n", sum);
return 0;
}
方法二:
a,,b往前走
#include <stdio.h>
#define max_n 4000000
int main() {
int a = 0, b = 1, sum = 0;
while (a + b <= max_n) {
b = a + b;
a = b - a;
if (b & 1) continue;
sum += b;
}
printf("%d\n", sum);
return 0;
}
方法三:卷動陣列
#include <stdio.h>
#define max_n 4000000
int fib[2] = {0, 1};
int main() {
int sum = 0, n = 1;
while (fib[n % 2] + fib[(n - 1) % 2] <= max_n) {
n++;
fib[n % 2] = fib[(n - 1) % 2] + fib[(n - 2) % 2];
if (fib[n % 2] & 1) continue;
sum += fib[n % 2];
}
printf("%d\n", sum);
return 0;
}
Answer:4613732
程式設計
#include <stdio.h>
#define max_n 600851475143LL
int main() {
int ans = 0, i = 2;
long long n = max_n;
while (i * i <= n) {
if (n % i == 0) ans = i;
while (n % i == 0) n /= i;
i++;
}//ans 爲什麼一定是素因子;素數篩的演算法
if (n != 1) ans = n;//爲什麼一定要判斷;怕n本身是一個素數
printf("%d\n", ans);
return 0;
}
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-ic4roMUI-1597297949307)(D:\Software\typora\Picture\image-20200809113138034.png)]
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-zEBMZ9Ln-1597297949308)(D:\Software\typora\Picture\image-20200809113202357.png)]
#include <stdio.h>
//base代表進位制,base = 10 就爲十進制
int is_val(int n, int base) {
int sum = 0, tmp = n;
while (tmp) {
sum = sum * base + tmp % base;
tmp /= base;
}
return sum == n;
}//實現任何一個十進制數位,在base進位制下是不是迴文數位
int main() {
int ans = 0;
for (int a = 100; a < 1000; a++) {
for (int b = a; b < 1000; b++) {
int t = a * b;
if (t > ans && is_val(t, 10)) ans = t;
}
}
printf("%d\n", ans);
return 0;
}
Answer:906609
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-Mi83ZbBO-1597297949309)(D:\Software\typora\Picture\image-20200809113250501.png)]
公式:a * b / gcd(a, b);
#include <stdio.h>
#define max_n 20
int gcd(int a, int b) {
return (b ? gcd(b, a % b) : a);
}
int main() {
int ans = 1;
for (int i = 1; i <= max_n; i++) {
ans *= i / gcd(ans, i);
}
printf("%d\n", ans);
return 0;
}
Answer: 232792560
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-XYuuQaXi-1597297949309)(D:\Software\typora\Picture\image-20200807131111204.png)]
方法一:
#include <stdio.h>
int main() {
int sum1 = 0, sum2 = 0;
for (int i = 1; i <= 100; i++) {
sum1 += i * i;
sum2 += i;
}
printf("%d\n", sum2 * sum2 - sum1);
return 0;
}
這樣時間複雜度是O(n)
方法二:sum2可以用前n項求和公式,sum1可以用前n項平方和的公式
#include <stdio.h>
#define n 100
int main() {
int sum2 = 5050; //前100項求和結果
int sum1 = (2 * n * n * n + 3 * n * n + n) / 6;//平方和求和公式
printf("%d\n", sum2 * sum2 - sum1);
return 0;
}
Answer:25164150
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-Ue5NiwSl-1597297949310)(D:\Software\typora\Picture\image-20200809181645494.png)]
滑動視窗法
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-IhVXwoIi-1597297949310)(D:\Software\typora\Picture\image-20200809182054576.png)]
#include <stdio.h>
#include <string.h>
#define max_n 1000
char num[max_n + 5];
int main() {
int len = 0;
while (~scanf("%s", num + len)) len = strlen(num);//回圈讀入
long long ans = 0, p = 1, zero = 0;
for (int i = 0; num[i]; i++) {
num[i] -= '0';
if (num[i]) p *= num[i];
else zero += 1;
if (i < 13) continue;
if (num[i - 13]) p /= num[i - 13];
else zero -= 1;
if (zero == 0 && p > ans) ans = p;
}
printf("%lld\n", ans);
return 0;
}
先將這1000個數存到input檔案中:./a.out < input ;
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-AHMFfiOV-1597297949311)(D:\Software\typora\Picture\image-20200809200540952.png)]
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-igcBh1bo-1597297949311)(D:\Software\typora\Picture\image-20200809200558155.png)]
Answer:23514624000
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-OwAW86JW-1597297949312)(D:\Software\typora\Picture\image-20200809201742538.png)]
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-QBzsEQD6-1597297949312)(D:\Software\typora\Picture\image-20200809201841309.png)]
#include <stdio.h>
int main() {
long long m = 40, n = 20, ans = 1;
while (m != 20 || n) {
if (m != 20) ans *= m--;
if (n && ans % n == 0) ans /= n--;
}//乘一項,除一項
printf("%lld\n", ans);
return 0;
}
Answer:137846528820
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-GEa5uTIW-1597297949313)(D:\Software\typora\Picture\image-20200810095404667.png)]
#include <stdio.h>
#define max_n 1000
//1~19數位的字母個數
static int num1[20] = {
0, 3, 3, 5, 4, 4, 3, 5, 5, 4, 3,
6, 6, 8, 8, 7, 7, 9, 8, 8
};
//整十的字母個數
static int num2[10] = {
0, 0, 6, 6, 5, 5, 5, 7, 6, 6
};
int get_letters(int n) {
if (n < 20) return num1[n];//20以內的情況
if (n < 100) return num2[n / 10] + num1[n % 10];//220~100的情況
if (n < 1000) {
if (n % 100 == 0) return num1[n / 100] + 7;
else return num1[n / 100] + 10 + get_letters(n % 100);
}//100~1000的情況
return 11;//1000的情況
}
int main() {
int sum = 0;
for (int i = 1; i <= max_n; i++) {
sum += get_letters(i);//用get_letters函數獲取i這個數位所需要的字母個數
}
printf("%d\n", sum);
return 0;
}
Answer:21124
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-8fOiRcsR-1597297949313)(D:\Software\typora\Picture\image-20200809100730932.png)]
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-TgOdov60-1597297949314)(D:\Software\typora\Picture\image-20200809103107799.png)]
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-V7Erd5Iz-1597297949314)(D:\Software\typora\Picture\image-20200809101413999.png)]
L1的邊長 = 3,右上角9 = L1邊長的平方;L2邊長 = 5,25 = L2邊長的平方;所以可確定,
右上角的數位規律 =
左上角的數位規律 =
左下角的數位規律 =
右下角的數位規律 =
求每一圈的和
程式設計
#include <stdio.h>
int main() {
int sum = 1;
for (int l = 3; l <= 1001; l += 2) {
sum += 4 * l * l - 6 * l + 6;
}
printf("%d\n", sum);
return 0;
}
Answer:669171001
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-8S8UVf8N-1597297949315)(D:\Software\typora\Picture\image-20200809103146428.png)]
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-IdMpEosc-1597297949315)(D:\Software\typora\Picture\image-20200809112215715.png)]
#include <stdio.h>
#include <math.h>
const int N = pow(9, 5) * 6;
int val(int n) {
int sum = 0, tmp = n;
while (tmp) {
sum += pow(tmp % 10, 5);
tmp /= 10;
}
return sum == n;
}
int main() {
int sum = 0;
for (int i = 2; i <= N; i++) {
if (!val(i)) continue;
sum += i;
}
printf("%d\n", sum);
return 0;
}
Answer:443839
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-71F0r0vo-1597297949316)(D:\Software\typora\Picture\image-20200809112621240.png)]
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-mvZZMOU3-1597297949317)(D:\Software\typora\Picture\image-20200809112636736.png)]
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-IRUY4Wue-1597297949317)(D:\Software\typora\Picture\image-20200810101756995.png)]
[外連圖片轉存失敗,源站可能有防盜鏈機制 機製,建議將圖片儲存下來直接上傳(img-7NxouQrI-1597297949318)(D:\Software\typora\Picture\image-20200810101823776.png)]
程式
#include <stdio.h>
#include <math.h>
//判斷數的位數
int digit(int n) {
return floor(log10(n)) + 1;
}
//判斷數位是否有重複
int add_to_num(int *num, int n) {
while (n) {
if (num[n % 10]) return 0;
num[n % 10] += 1;
n /= 10;
}
return 1;
}
//判斷a,b,c是否有重複數位
int is_val(int a, int b, int c) {
if (digit(a) + digit(b) + digit(c) - 9) return 0;//確保包含1~9所有數位
int num[10] = {0};
num[0] = 1;
int flag = 1;
flag = flag && add_to_num(num, a);
flag = flag && add_to_num(num, b);
flag = flag && add_to_num(num, c);
return flag;
}
int keep[10000] = {0};//標記陣列
int main() {
int sum = 0;
for (int a = 1; a < 100; a++) {
for (int b = a + 1; b < 10000; b++) {
if (!is_val(a, b, a * b)) continue;
if (keep[a * b]) continue;
sum += a * b;
keep[a * b] = 1;//將每一個a * b結果結束後置爲1,防止重複
printf("%d * %d = %d\n", a, b, a * b);
}
}
printf("%d\n", sum);
return 0;
}
Answer: 45228
#include <stdio.h>
#include <inttypes.h>
//遞回過程
int64_t Triangele(int64_t n) {
return n * (n + 1) / 2;
}
int64_t Pentagonal(int64_t n) {
return n * (3 * n - 1) / 2;
}
int64_t Hexagonal(int64_t n) {
return n * (2 * n - 1);
}
//二分法查詢
int64_t binary_search(int64_t (*func)(int64_t), int64_t n, int64_t x) {
int64_t head = 1, tail = n, mid;
while (head <= tail) {
mid = (head + tail) >> 1;
if (func(mid) == x) return 1;
if (func(mid) < x) head = mid + 1;
else tail = mid - 1;
}
return 0;
}
//主函數
int main() {
int64_t n = 143;
while (1) {
n++;
int64_t tmp = Hexagonal(n);
if (!binary_search(Pentagonal, 2 * n, tmp)) continue;
break;
}
printf("%" PRId64 "\n", Hexagonal(n));
return 0;
}
Answer:1533776805
add_to_num(num, c);
return flag;
}
int keep[10000] = {0};//標記陣列
int main() {
int sum = 0;
for (int a = 1; a < 100; a++) {
for (int b = a + 1; b < 10000; b++) {
if (!is_val(a, b, a * b)) continue;
if (keep[a * b]) continue;
sum += a * b;
keep[a * b] = 1;//將每一個a * b結果結束後置爲1,防止重複
printf("%d * %d = %d\n", a, b, a * b);
}
}
printf("%d\n", sum);
return 0;
}
Answer: 45228
## 45 Triangular, pentagonal, and hexagonal(三角形數、五邊形數和六角形數)
1. 題目描述
<img src="D:\Software\typora\Picture\image-20200809213941602.png" alt="image-20200809213941602" style="zoom:67%;" />
2. 程式
```c
#include <stdio.h>
#include <inttypes.h>
//遞回過程
int64_t Triangele(int64_t n) {
return n * (n + 1) / 2;
}
int64_t Pentagonal(int64_t n) {
return n * (3 * n - 1) / 2;
}
int64_t Hexagonal(int64_t n) {
return n * (2 * n - 1);
}
//二分法查詢
int64_t binary_search(int64_t (*func)(int64_t), int64_t n, int64_t x) {
int64_t head = 1, tail = n, mid;
while (head <= tail) {
mid = (head + tail) >> 1;
if (func(mid) == x) return 1;
if (func(mid) < x) head = mid + 1;
else tail = mid - 1;
}
return 0;
}
//主函數
int main() {
int64_t n = 143;
while (1) {
n++;
int64_t tmp = Hexagonal(n);
if (!binary_search(Pentagonal, 2 * n, tmp)) continue;
break;
}
printf("%" PRId64 "\n", Hexagonal(n));
return 0;
}
Answer:1533776805