Coder Social home page Coder Social logo

old_blog's Introduction

  • 👋 Hi, I’m @InnocentLi
  • 👀 I’m interested in Java JavaScript C++
  • 🌱 I’m currently learning Vue and React
        Person person = new Person();
        person.Name = "Wenhao Li";
        person.WeChat = "9304893";//this is real
        DateFormat date = new SimpleDateFormat("yyyy-MM-dd");
        person.Birthday = date.parse("1996-12-04");
        String major[] = { "Java", "JavaScript", "C++" };
        person.Major = major;
        String experience[] = { "DiDi", "Alibaba"};
        person.WorkExperience = experience;
        person.IWantSay("JS is a f**king language");

2015.6-2019.7 黒龍江大学

2020.12 - 2022.1 ハルビン遠洲科技会社(正社員)
2018.12-2019.12 アリババ株式会社(Alibaba Group)(正社員)
2018.4 - 2018.11 ディディチューシン (Didi Chuxing Technology)(インターンシップ)
2017.9 - 2018.3 チューナー(Qunar Technology)(インターンシップ)

old_blog's People

Contributors

innocentli avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

Forkers

meng0311 oyhaimon

old_blog's Issues

欧拉第二十八题Number spiral diagonals

没啥好说的,直接上代码👇

/*************************************************************************
	> File Name: 28.cpp
	> Author: 
	> Mail: 
	> Created Time: 四  5/ 3 14:21:38 2018
 ************************************************************************/

#include<iostream>
#include<stdio.h>
#define NUM 1001
using namespace std;
int main(){
    int n = (NUM-1)*2;
    int k = 3;
    int l = 2;
    int sum=0;
    for(int i = 1;i<=n;i++){        
        sum+=k;
        printf("K:%d\n",k);
        
        k+=l;
        if(i%4==3){
            l+=2;
        }     
    }
    printf("sum:%d\n",sum+1);

}

PS:之前给女朋友讲题还讲错了,fk

移动端Web开发方案

常用的布局思路

媒体查询

body {
    background-color:lightgreen;
}

@media screen and (max-width: 300px) {
    body {
        background-color:lightblue;
    }
}
//如果screen是小于300px会变成淡蓝色;

一个常见的例子

body{
    background-color:#0033FF;
}
@media screen and (max-width: 960px){
    body{
    background-color:#FF6699
    }
}

@media screen and (max-width: 768px){
    body{
    background-color:#00FF66;
    }
}

@media screen and (max-width: 550px){
    body{
    background-color:#6633FF;
    }
}

@media screen and (max-width: 320px){
    body{
    background-color:#FFFF00;
    }
}

栅格化布局

掘金:栅格化系统

流式布局

也就是俗称的百分比布局,因为宽度是百分比,但是高度是按px来写的
👆以上方法均为传统方案,新方案👇

利用Flexible

例如UI的设计稿是230px,我们就利用函数将它转换成rem.(230px / 16px = 14.375rem)

rem?

∵font-size:16px;
∴1 rem = 16px;

css常见单位

px:像素
rem: 相对于根元素(即html元素)font-size计算值的倍数
em: 相对于父元素font-size计算值的倍数
∴1. em的值并不是固定的;
∴2. em会继承父级元素的字体大小。

解决方案

假设我有iPhone 5(320px) iPhone 6(375) iPhone 8 Plus (414) iPhone X(375)四款手机
分成10份就是三种布局 32px / 37.5px / 41.4px 也就是说我的1 rem 在不同手机下是不同显示效果
所以它们的1 rem就是 32px / 37.5px / 41.4px
我有一个宽 320px的图片(屏幕宽750px) ,我的图片占 4.2666rem(360px / (750 px / 10 ))
所以我的iPhone 5 占比 4.266632px
所以我的iPhone 6/X 占比 4.2666
37.5px
所以我的iPhone 8 Plus 占比 4.2666*37.5px

代码实现

document.addEventListener('DOMContentLoaded',function (e){
    document.getElementsByTagName('html')[0].style.fontSize = 
window.innerWidth / 10 + 'px';
},false);
@function pxtorem($px){
        $rem : 75px;
        @return ($px/$rem) + rem;
}

#img{
       width: pxtorem(320px);
}

viewport 和 dpr

C++中指针和引用的区别(转)

从概念上讲。指针从本质上讲就是存放变量地址的一个变量,在逻辑上是独立的,它可以被改变,包括其所指向的地址的改变和其指向的地址中所存放的数据的改变。

而引用是一个别名,它在逻辑上不是独立的,它的存在具有依附性,所以引用必须在一开始就被初始化,而且其引用的对象在其整个生命周期中是不能被改变的(自始至终只能依附于同一个变量)。

在C++中,指针和引用经常用于函数的参数传递,然而,指针传递参数和引用传递参数是有本质上的不同的:

指针传递参数本质上是值传递的方式,它所传递的是一个地址值。值传递过程中,被调函数的形式参数作为被调函数的局部变量处理,即在栈中开辟了内存空间以存放由主调函数放进来的实参的值,从而成为了实参的一个副本。值传递的特点是被调函数对形式参数的任何操作都是作为局部变量进行,不会影响主调函数的实参变量的值。

而在引用传递过程中,被调函数的形式参数虽然也作为局部变量在栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何操作都影响了主调函数中的实参变量。

引用传递和指针传递是不同的,虽然它们都是在被调函数栈空间上的一个局部变量,但是任何对于引用参数的处理都会通过一个间接寻址的方式操作到主调函数中的相关变量。而对于指针传递的参数,如果改变被调函数中的指针地址,它将影响不到主调函数的相关变量。如果想通过指针参数传递来改变主调函数中的相关变量,那就得使用指向指针的指针,或者指针引用。

为了进一步加深大家对指针和引用的区别,下面我从编译的角度来阐述它们之间的区别:

程序在编译时分别将指针和引用添加到符号表上,符号表上记录的是变量名及变量所对应地址。指针变量在符号表上对应的地址值为指针变量的地址值,而引用在符号表上对应的地址值为引用对象的地址值。符号表生成后就不会再改,因此指针可以改变其指向的对象(指针变量中的值可以改),而引用对象则不能修改。

最后,总结一下指针和引用的相同点和不同点:

★相同点:

●都是地址的概念;

指针指向一块内存,它的内容是所指内存的地址;而引用则是某块内存的别名。

★不同点:

●指针是一个实体,而引用仅是个别名;

●引用只能在定义时被初始化一次,之后不可变;指针可变;引用“从一而终”,指针可以“见异思迁”;

●引用没有const,指针有const,const的指针不可变;

●引用不能为空,指针可以为空;

●“sizeof 引用”得到的是所指向的变量(对象)的大小,而“sizeof 指针”得到的是指针本身的大小;

●指针和引用的自增(++)运算意义不一样;

●引用是类型安全的,而指针不是 (引用比指针多了类型检查

JavaScript事件

事件分级

DOM 0 ,DOM 2,DOM 3

//DOM0
element.onclick = function (){}
//DOM2
element.addEventListener("click",function(){},false)
//DOM3
element.addEventListener("keyup",function(){},false)

其中里面最后个参数是代表捕获(true)和冒泡(false),默认是false冒泡

DOM事件类型:冒泡和捕获

冒泡是从
window→document→html→body→div→text
捕获是从
window←document←html←body←div←text
其中html是利用document.documentElement获得

DOM事件api

event.preventDefault() //阻止默认事件
event.stopPropagation()  //阻止冒泡
event.stopImmediatePropagation() //官方解释。阻止调用相同事件的其他侦听器。
event.currentTarget() 
event.target  

event.preventDefault()

阻止默认事件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>event.preventDefault()</title>
</head>
<body>
    <p>请点击复选框控件</p>
    <form>
        <label for="id-checkbox">Checkbox</label>
        <input type="checkbox" id="id-checkbox" name="checkbox" />
    </form>
    <script>
        document.querySelector("#id-checkbox").addEventListener("click", function(event){
            event.preventDefault();  //阻止该复选框被勾选
            setTimeout(function (){
              alert("preventDefault会阻止该复选框被勾选.")
            },0)
        }, false);
    </script>
</body>
</html>

当你选择时候会触发此事件(alert),并且不会被选中

stopImmediatePropagation()

某个元素有多个相同类型事件的事件监听函数,则当该类型的事件触发时,多个事件监听函数将按照顺序依次执行.如果某个监听函数执行了 event.stopImmediatePropagation()方法,则除了该事件的冒泡行为被阻止之外(event.stopPropagation方法的作用),该元素绑定的后序相同类型事件的监听函数的执行也将被阻止.

<!DOCTYPE html>
<html>
    <head>
        <style>
            p { height: 30px; width: 150px; background-color: #ccf; }
            div {height: 30px; width: 150px; background-color: #cfc; }
        </style>
    </head>
    <body>
        <div>
            <p>paragraph</p>
        </div>
        <script>
            document.querySelector("p").addEventListener("click", function(event)
            {
                alert("我是p元素上被绑定的第一个监听函数");
            }, false);
            document.querySelector("p").addEventListener("click", function(event)
            {
                alert("我是p元素上被绑定的第二个监听函数");
                event.stopImmediatePropagation();
                //执行stopImmediatePropagation方法,阻止click事件冒泡,并且
                //阻止p元素上绑定的其他click事件的事件监听函数的执行.
            }, false);
            document.querySelector("p").addEventListener("click", function(event)
            {
                alert("我是p元素上被绑定的第三个监听函数");
                //该监听函数排在上个函数后面,该函数不会被执行.
            }, false);
            document.querySelector("div").addEventListener("click", function(event)
            {
                alert("我是div元素,我是p元素的上层元素");
                //p元素的click事件没有向上冒泡,该函数不会被执行.
            }, false);
        </script>
    </body>
</html>

event.currentTarget()

如下代码所示,

   <ul id="f">
                <li class="item1">1</li>
                <li class="item2">2</li>
     </ul>
  <script type="text/javascript">
        document.getElementById("f").onclick = function  (event) {
            console.log(event.target);//<li class="item2">
            console.log(event.currentTarget);//<ul id="f">
        }
    </script>

event.target

事件属性可返回事件的目标节点

<html>
 <body>
  <ul id="ul">
  <span>1</span>
  <p>2</p>
  <li>3</li>
  </ul>
  <script>
    var ul = document.getElementById("ul");
             ul.onclick = function(event){
             var tar = event.target;
             var tagName = tar.nodeName.toLowerCase();
             alert("你点击了:"+tagName);
             event.preventDefault();
 }

 </script>

</body>
</html>

下面的demo是创建一个元素并点击删除删除这个元素的例子。

<head>
</head>
<input type="text" id="text">
<input type="button" value="添加" id="button">
<ul>
  <li>第1个
    <button class="btn" id="1">删除</button>
  </li>
  <li>第2个
    <button class="btn" id="2">删除</button>
  </li>
  <li>第3个
    <button class="btn" id="3">删除</button>
  </li>
</ul>

<body>
  <script>
    var button = document.getElementById("button");
    var text = document.getElementById("text");
    var ul = document.getElementsByTagName("ul")[0];
    var btnClass = document.getElementsByClassName("btn");
    button.onclick = function () {
      var deleteButton = document.createElement("button");
      var value = text.value;
      deleteButton.setAttribute("class", "btn");
      var deleteText = document.createTextNode("删除");
      deleteButton.appendChild(deleteText);
      var li = document.createElement("li");
      var liText = document.createTextNode(value);
      //在此处添加一个组件,包含text和button,后面会将button绑定删除事件
      li.appendChild(liText);
      li.appendChild(deleteButton);
      ul.appendChild(li);
      for (var i = 0; i < btnClass.length; i++) {
        btnClass[i].onclick = function () {
          console.log(this, this.parentNode, this.parentNode.parentNode);
          this.parentNode.parentNode.removeChild(this.parentNode);
        }
      }
    }
    for (var i = 0; i < btnClass.length; i++) {
      btnClass[i].onclick = function () {
      //绑定事件后进行删除
        this.parentNode.parentNode.removeChild(this.parentNode);
      }
    }
  </script>
</body>

</html>

欧拉第一题Multiples of 3 and 5

容斥原理

👆基本思路就是这些
求出在1000里被3和5整除的数
思路1:

#include <stdio.h>
int main(){
    int sum = 0;
    for(int i = 0;i<1000;i++){
        if(i % 3 == 0){
             sum += i;
        }
        if(i % 5 == 0){
             sum += i;
        }
        if(i % 3 == 0&&i % 5 ==0){
             sum -=i;
        }
    }
}

思路2:

#include <stdio.h>
int main() {
    int sum = 0;
    for (int i = 0; i < 1000; i++) {
        if (i % 3 == 0 || i % 5 == 0)
            sum += i;
    }
    printf("%d\n", sum);
}

结构体调用sort

最近做题发现对结构体进行sort排序有点卡壳,所以整理一下

#include<iostream>
#include<algorithm>
using namespace  std;
struct s{
   int numerator;
   int denominator;
   double quotient;
}A[25600];
int cmp(const s &a,const s &b){
   return a.quotient<b.quotient;
}
int main(){
      sort(A, A+n, cmp);

比如此题我需要对quotient进行排序,那么我们的条件判断会在自己写的cmp函数中进行判断

欧拉第五题Smallest multiple

gcd最经典的做法,

#include <stdio.h>
#include <stdlib.h>
int gcd(long long a,long long b) {
	if (!b) return a;
	return gcd(b, a % b);   //这个可以自己打印手动模拟一下工作原理,不难理解
}
int main() {
	long long ans = 1;
	for (long long i = 1; i <= 20; i++) {
		ans *= i / gcd(i, ans);   //看了快半个小时,先挖个坑.
               printf("ans:%d i:%d : gcd: %d\n",ans,i,gcd(i, ans));
	}
       //每次用i的值取除ans和i的最小公倍数,
	printf("%lld\n", ans);
	return 0;
}

欧拉第三十四题Digit factorials

通过一个函数来进行10进制和2进制的回文判断,

#include <stdio.h>
#include <inttypes.h>
#define MAX_N 1000000   //假设的值,具体请参考估计最大值法
int32_t reverseNum(int32_t n, int32_t base) { // 比如我来个12345
	if (base <= 1) return 0;
	int32_t x = 0;
	while (n) {
		 //这段代码的意思是,把这个数低位和高位进行交换
		x = x * base + n % base; 
//第一次是。  0 = 0* 10 + 12345%10(其实就是5),放入最高位,然后全部扩大10倍;
//让新提取的数字放入x中直到全部提取完毕.     
		n /= base;
	}
	return x;
}
int32_t main() {
	int32_t sum = 0, base2, base10;
	for (int32_t i = 1; i <= MAX_N; i++) {
		base2 = reverseNum(i, 2);
		base10 = reverseNum(i, 10);
		if (base2 == base10 && base10 == i) sum += i;
	}
	printf("%d\n", sum);
    return 0;
}

小模板总结

判断一个数有几位数字

	a =31456;
	printf("%d",pow(10,floor(log10(a))));

快速求是否互质

bool isrp(int a, int b){
   if(a <=0 || b<=0 || a==b){ 
      return false;
   }else if(a==1 || b==1){  
            return true;
   }else{
      while(1){
         int t = a%b;
         if(t == 0){
            break;
         }else{
            a = b;
            b = t;
         }
      }
      if( b > 1){
         return false;
      }else{        
         return true;
      }
   }
}

Cprint函数实现

/*by hug*/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <inttypes.h>
#include <math.h>

int __pass(va_list *args) { return 0; }
int __decimal(va_list *args) {
    int number = va_arg(*args, int);
    uint32_t temp_number = number;
    int ret = 0, k = 0, flag = (number < 0);
    if (flag) temp_number = -number;
    #define PUT(ch) putc(ch, stdout), ret++;
    if (temp_number == 0) {
        PUT('0');
        return 1;
    }
    if (flag) PUT('-');
    k = (uint32_t)log10(temp_number);
    do {
        PUT(temp_number / (uint32_t)pow(10, k) + '0');
        temp_number %= (uint32_t)pow(10, k);
    } while (k--);
    #undef PUT
    return ret;
}

int print(const char *frm, ...) {
    int ret = 0;
    int (*hash_func[128])(va_list *);
    for (int i = 0; i < 128; i++) {
        hash_func[i] = __pass;
    }
    hash_func['d'] = __decimal;
    #define PUT(ch) putc(ch, stdout), ret++;
    va_list args;
    va_start(args, frm);
    while (frm[0]) {
        switch (frm[0]) {
            case '%': {
                frm++;
                ret += hash_func[frm[0]](&args);
            } break;
            default :
                PUT(frm[0]);
                break;
        }
        frm++; 
    }
    #undef PUT
    return ret;
}

int main() {
    print("hello world\n");
    print("number : %d %d\n", 123, 456);
    print("number : %d %d\n", 120, 456);
    print("number : %d %d\n", 0, 456);
    print("number : %d %d\n", -123, 456);
    print("number : %d %d\n", INT32_MAX, INT32_MIN);
    return 0;
}

Windows下递归所有文件的修改时间

@ECHO OFF
powershell.exe -command "Get-Childitem -path 'C:\Users\DELL\Desktop\毕业设计' -Recurse | foreach-object { $_.LastWriteTime = Get-Date; $_.CreationTime = Get-Date }" 
PAUSE

欧拉第二题Even Fibonacci numbers

斐波那契

典型的斐波那契**
求出偶数项斐波那契不超过400万的和

思路1:

#include <stdio.h>
int main() {
	int f[10000]={0};
	f[1] = 1;
	f[2] = 2;
    int sum = 0;
	for(int i = 1;f[i]<=4000000;i++){
		f[i+2] = f[i+1] + f[i];
    }
	for(int i = 1;f[i]<=4000000;i++){
		if(f[i]%2==0){
            sum += f[i];
        }
	}
	  //  
	printf("%d\n",sum);
}

思路2:

#include <stdio.h>
int main() {
	int a, b, c, sum = 0;
	a = 1; b = 1;
	while (b < 4000000) {
		if (b % 2 == 0){
			sum += b;
		} 
		c = b;
		b = a + b;
		a = c;   
	}
	printf("%d\n", sum);
	return 0;
}

欧拉第六题Sum square difference

11 + 22 + ... + 1010 = 385
(1 + 2 + ... + 10)
(1 + 2 + ... + 10) = 55*55 = 3025
问从1到100

#include <stdio.h>
#include <stdlib.h>
int main() {
    int32_t sum1 = 0, sum2 = 0;
    for (int32_t i = 1; i <= 100; ++i) {
        sum1 += i * i;
        sum2 += i;
    }
    printf("%d\n", sum2 * sum2 - sum1);
    return 0;
}

跨域解决方案

Ajax和跨域

跨域发生原因

原因1.浏览器端口/协议/域名不一样 2.发送xhr对象 跨域产生的原因是客户端的限制

跨域存在的意义

跨域解决思路:

1.利用jsonp ,通过动态创建的script标签进行跨域访问。(服务器需要改动)
跨域服务端修改:
2.通过服务器发送字段,让浏览器支持跨域
Access-Control-Allow-origin :true
3. 正向代理: 我借助与我的服务器, 像数据服务器发送数据, 我的服务器只需要向数据服务器发送get请求即可

  1. 反向代理: 和正向代理类似, 但是不借助于脚本, 而是直接使用 服务器映射 url.

eg: 我们的 url 是 http://studyit.com

数据服务器的 url 是 http://api.botue.com/login
在apache配置一个 url 的代理映射
理论上使用 url: http://studyit.com/api 是在网站根目录下找 api 文件夹
但是现在 apache 提供一个映射的功能, 将 /api 映射到 http://api.botue.com
有了这个映射, 那么 访问 http://api.botue.com/login 就可以利用 /api/login来访问了
5.浏览器关闭检查进行跨域

利用 --args --disable-web-security --user-data-dir

Apache HTTP Server

JSONP跨域方式解析

解释 Name Status Protocol Type Content-Type
正常 Get1 200 http/1.1 xhr application/json
jsonp Get1?callback=JQuery412…. 200 http/1.1 script application/javascript

根本区别是Type值不同,底层原理也不相同,callback是返回的是夹杂json的js代码片段。

如果改成callback2会发生获取的值是json,这也是后台和前端约定俗成的方式,如果后台是callback,返回改成callbak2,会发生获取值callback2=json的形式,

参数使用一次就会被销毁例如jquery源码中体现的

	if ( s.crossDomain ) {
		var script, callback;
		return {
			send: function( _, complete ) {
				script = jQuery( "<script>" ).prop( {
					charset: s.scriptCharset,
					src: s.url
				} ).on(
					"load error",
					callback = function( evt ) {
						script.remove();
						callback = null;
						if ( evt ) {
							complete( evt.type === "error" ? 404 : 200, evt.type );
						}
					}
				);

				// Use native DOM manipulation to avoid our domManip AJAX trickery
				document.head.appendChild( script[ 0 ] );
			},
			abort: function() {
				if ( callback ) {
					callback();
				}
			}
		};
	}

callback会返回jQuery110206957915709923779_1519612937942_这个值,这个值后面会有下划线,但是如果加上Cache: 如果为true,表示结果可以被缓存,callback后面的请求参数下划线消失,

callback的意义

你到一个商店买东西,刚好你要的东西没有货,于是你在店员那里留下了你的电话,过了几天店里有货了,店员就打了你的电话,然后你接到电话后就到店里去取了货。在这个例子里,你的电话号码就叫回调函数,你把电话留给店员就叫登记回调函数,店里后来有货了叫做触发了回调关联的事件,店员给你打电话叫做调用回调函数,你到店里去取货叫做响应回调事件。(转自zh)

JSONP弊端

1.服务器需要改动支持

2.只支持GET(强行请求post也会自动生成GET请求)

3.发送的不是XHR请求(废话)

跨域简单请求和非简单请求

简单请求:

方法为GET,HEAD,POST

请求header里面

无自定义头

Content-Type为一下几种:

​ text/plain

​ mulipart/from-data

​ application/x-www-form-urlenoded

非简单请求/复杂请求:

​ put,delete方法的ajax请求

​ 发送json格式的ajax请求

​ 带自定义头的ajax请求

复杂请求表面上看起来和简单请求使用上差不多,但实际上浏览器发送了不止一个请求。其中最先发送的是一种"预请求",此时作为服务端,也需要返回"预回应"作为响应。预请求实际上是对服务端的一种权限请求,只有当预请求成功返回,实际请求才开始执行。

预请求以OPTIONS形式发送,当中同样包含域,并且还包含了两项CORS特有的内容:

OPTIONS预检命令缓存

添加Access-Control-Max-Age头部命令 可以起到缓存作用

可以参考https://www.poorren.com/cross-origin-resource-sharing-simple-complex

带Cookie的跨域

不可以用Access

XHR的用法

ajax跨域的一个重要对象就是XMLHttpRequest对象,

使用 XHR 对象时,要调用的第一个方法是 open()。

("get"、"post"等)、请求的 URL,是否异步发送请求

     xhr.open("get", "example.php", false);

这行代码会启动一个针对 example.php 的 GET 请求。有关这行代码,需要说明两点:一是 URL 5相对于执行代码的当前页面(当然也可以使用绝对路径);二是调用 open()方法并不会真正发送请求,而只是启动一个请求以备发送。

然后调用 send()方法才能实现发送

xhr.send(null);

响应之后数据会自动添加到XHR 对象的属性,

  • responseText:作为响应主体被返回的文本。

  • responseXML:如果响应的内容类型是"text/xml"或"application/xml",这个属性中将保存包含着响应数据的 XML DOM 文档。

  • status:响应的 HTTP 状态。

  • statusText:HTTP 状态的说明

代码如下

var xhr = new XMLHttpRequest();
xhr.open("get", "example.txt", false);
xhr.send(null);
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
   alert(xhr.responseText);
} else {
    alert("Request was unsuccessful: " + xhr.status);
}

根据返回的状态代码,这个例子会显示由服务器返回的内容/错误消息。通过检测 status 来决定下一步的操作,不要依赖 statusText,因为后者在跨浏览器使 用时不太可靠。另外,无论内容类型是什么,响应主体的内容都会保存到 responseText 属性中;而 对于非 XML 数据而言,responseXML 属性的值将为 null。

素数筛

素数筛在欧拉计划里用到过,在这里解释一下,素数筛是如何工作的👇
1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
31 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
1不算,我从二开始找,当我第一遍遍历的时候,会将2和它的倍数进行遍历,
1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
31 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
当我遍历完成后,我会继续将3的倍数进行标注,注意,我起点完全可以从3的平方开始寻找,(因为3*2的已经标记完了)
1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
31 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
以此类推

代码实现👇

#include<stdio.h>
#define MAX 10000
int main(){
    int prem[MAX]={0};
    for(int i = 2;i<MAX;i++){
        for(int j=i*i;j<MAX;j+=i){
            prem[j] = 1;
        }
    }
    for(int i = 2;i<30;i++){
        if(!prem[i]){
            printf("%d",i);
        }
    }
}

大家有兴趣可以看看莫比乌斯函数

欧拉第三十题Digit fifth powers

介绍一个*操作,可以用python来绘制表格,mac用户可以直接command+C command+V到 终端(python环境下)

import numpy as np
import matplotlib.pyplot as plt
plt.figure(1) # 创建图表1
x = np.linspace(0, 6, 300) # 在0--6范围之间,生成300个点
y1 = [10**z for z in x]    # 得到 f(n) 函数的 y 值数组
y2 = [(9**5)*z for z in x] # 得到 g(n) 函数的 y 值数组
plt.figure(1)
plt.title('f(n) vs g(n)')
p1 = plt.plot(x, y1, label="$f(n)=10^n$");
p2 = plt.plot(x, y2, label="$g(n)=9^5 * n$");
plt.xlabel('n digits')
plt.ylabel('num value')
plt.legend() # 显示图例
plt.show() # 显示图表

先确定上界
9的5次方*6
为什么是这个上界?因为一个7位数的每位的5次方和,不可能成为一个7位数,最多是一个六位数的每一位5次方,等于一个6位数,故上界9!*6

#include <stdio.h>
#include <math.h>
#include <inttypes.h>
#define MAX_N 354294 // 9^5 * 6
int32_t isFifthPowerNum(int32_t n) {
    int32_t sum = 0, x = n;
    while (n) {     原始值   ➡️ 12345
        sum += (int32_t)pow(n % 10, 5);    //每次取最短位   ➡️  5 
        n /= 10;   //    新值     ➡️  1234   
    }
    return sum == x;
}
int32_t main() {
    int32_t total = 0;
    for (int32_t i = 2; i <= MAX_N; i++) {
        if (isFifthPowerNum(i)) total += i;
    }
    printf("%d\n", total);
    return 0;
}

Bug?

let config = {
    ImgSrc:{  // 图片地址
        Home:"'https://img1.qunarzz.com/desmisact/images/1806/fe/fdf7437a132f25.png'",
        CountDown: "./img/dao.png "
    },
    Phone:{  // 手机宽高
        width: window.screen.availWidth,
        height: window.screen.availHeight,
        htmlbackground: ['#FFDF40', '#7ABE45', '#FFACB0']
    },
    templete:{
        FirstPlayBtn:"<div id='FirstPlayBtn'></div>"
    }
   
}

var app = document.getElementById("app");
var body = document.getElementsByTagName("body")[0];
var b = 3;
window.onload = function () {
    init();
}

function init(Dom){
    console.log(b);
    let body = document.getElementsByTagName("body")[0];
    body.style.background = config.Phone.htmlbackground[0];
    app.style.width = config.Phone.width+"px";
    app.style.height = config.Phone.height + "px";
    app.style.background = config.Phone.htmlbackground[0];
    app.innerHTML = "<img src=" + imgsrc.Home + "style=" + "width:100%;" + ">";
    app.innerHTML+=config.templete.FirstPlayBtn;
    let FirstPlayBtn = document.getElementById("FirstPlayBtn");
    FirstPlayBtn.addEventListener("click", screen1);
}

function screen1() {
    FirstPlayBtn.removeEventListener("click", screen1);
    body.style.background = Phone.htmlbackground[1];
    app.style.background = Phone.htmlbackground[1];
    app.innerHTML = "<img src=" + "./img/dao.png " + "style=" + "width:100%;" + ">";
   // setTimeout(game.init, 1000);
}

求因子和和因子个数(欧拉)

最强(爆改)模版,性能超快

#include <stdio.h>
#include <stdint.h>
#define MAX_N 1000000

int32_t m_num[MAX_N + 5] = {0};    //最小素因子最高次幂 2的3次方 = 8
int32_t prime[MAX_N] = {0};
int32_t d_num[MAX_N + 5]  = {0};   //因子和
int32_t snum[MAX_N+5]={0};    //因子个数

int32_t main() {
	for (int32_t i = 2; i <= MAX_N; i++) {
		if (!prime[i]) { 
			m_num[i] = i;    //素数
			d_num[i] = i + 1;
			prime[++prime[0]] = i;
			snum[i] = 2;
		}
		for (int32_t j = 1; j <= prime[0]; j++) {
			if(i * prime[j]>MAX_N) break;
			prime[i*prime[j]] =1;
			if (i % prime[j] == 0) {//    24。=     12   * 2的素因子    
				m_num[i * prime[j]] = m_num[i] * prime[j];
				d_num[i * prime[j]] = d_num[i] * (m_num[i] * prime[j] * prime[j] - 1) / (m_num[i] * prime[j] - 1);
					// 个数
					int knum = 0,pre_i = i;
					while (pre_i % prime[j]==0) pre_i /= prime[j],knum++;
					snum[prime[j]*i] = snum[i] / (knum +1) * (knum+2);
					//
				break;
			} else {      //6  = 3 * 2;
				m_num[i * prime[j]] = prime[j];
				d_num[i * prime[j]] = d_num[prime[j]] * d_num[i];
				//个数
				snum[prime[j]*i] = snum[prime[j]] * snum[i];
				//
			}
	    }
	}
    int max = 0;
    long long max2 = 0;
    for(int i = 2;i<=1000000;i++){
        if(d_num[i]>max){
            max = d_num[i];
        }
        if(d_num[i]*snum[i]>max){
	    max2 = d_num[i]*snum[i];
	    }
    }
      //18   2  3pingfang
	printf("测试12:%d %d %d\n", d_num[12],m_num[12],snum[12]);
	printf("测试24:%d %d %d\n", d_num[24],m_num[24],snum[24]);
	printf("测试11:%d %d %d\n", d_num[428407],m_num[428407],snum[428407]);
    printf("%d\n",max);
    printf("%lld\n",max2);
}

Nginx

Nginx

介绍

Nginx是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器。 Nginx是老毛子写的.牛逼不?

其将源代码以类BSD许可证的形式发布,因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。2011年6月1日,nginx 1.0.4发布。

Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行。其特点是占有内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页服务器中表现较好,

高性能,反向代,很稳定,高并发

按照官方的定义,nginx是一个HTTP服务器,也是一个反向代理服务器。apache应 该为大家所熟知,而nginx就是类似apache的提供静态网页的web服务器,相比于 apache的多进程多线程的并发模型,而nginx是基于事件的异步IO的并发模型,性 能更好,而且nginx是一个轻量级的服务器。

Nginx和apache

nginx 相对 apache 的优点

  • 轻量级,同样起web 服务,比apache 占用更少的内存及资源
  • 抗并发,nginx 处理请求是异步非阻塞的,而apache 则是阻塞型的,在高并发下nginx 能保持低资源低消耗高性能
  • 高度模块化的设计,编写模块相对简单
  • 社区活跃,各种高性能模块出品迅速啊

apache 相对nginx 的优点

补充

1、作为 Web 服务器:相比 Apache,Nginx 使用更少的资源,支持更多的并发连接,体现更高的效率,这点使 Nginx 尤其受到虚拟主机提供商的欢迎。在高连接并发的情况下,Nginx是Apache服务器不错的替代品: Nginx在美国是做虚拟主机生意的老板们经常选择的软件平台之一. 能够支持高达 50000 个并发连接数的响应, 感谢Nginx为我们选择了 epoll and kqueue 作为开发模型.
Nginx作为负载均衡服务器: Nginx 既可以在内部直接支持 Rails 和 PHP 程序对外进行服务, 也可以支持作为 HTTP代理 服务器对外进行服务. Nginx采用C进行编写, 不论是系统资源开销还是CPU使用效率都比 Perlbal 要好很多.
2、Nginx 配置简洁, Apache 复杂 ,Nginx 启动特别容易, 并且几乎可以做到7*24不间断运行,即使运行数个月也不需要重新启动. 你还能够不间断服务的情况下进行软件版本的升级 . Nginx 静态处理性能比 Apache 高 3倍以上 ,Apache 对 PHP 支持比较简单,Nginx 需要配合其他后端来使用 ,Apache 的组件比 Nginx 多.
3、最核心的区别在于apache是同步多进程模型,一个连接对应一个进程;nginx是异步的,多个连接(万级别)可以对应一个进程 .
4、nginx的优势是处理静态请求,cpu内存使用率低,apache适合处理动态请求,所以现在一般前端用nginx作为反向代理抗住压力,apache作为后端处理动态请求。

(以上转自知乎)https://www.zhihu.com/question/19571087

Nginx为什么比Apache Httpd高效:原理篇(转)

一、进程、线程?

进程是具有一定独立功能的,在计算机中已经运行的程序的实体。在早期系统中(如linux 2.4以前),进程是基本运作单位,在支持线程的系统中(如windows,linux2.6)中,线程才是基本的运作单位,而进程只是线程的容器。程序 本身只是指令、数据及其组织形式的描述,进程才是程序(那些指令和数据)的真正运行实例。若干进程有可能与同一个程序相关系,且每个进程皆可以同步(循 序)或异步(平行)的方式独立运行。现代计算机系统可在同一段时间内以进程的形式将多个程序加载到存储器中,并借由时间共享(或称时分复用),以在一个处 理器上表现出同时(平行性)运行的感觉。同样的,使用多线程技术(多线程即每一个线程都代表一个进程内的一个独立执行上下文)的操作系统或计算机架构,同 样程序的平行线程,可在多 CPU 主机或网络上真正同时运行(在不同的CPU上)。

二、常见Web服务方式

2.1 三种工作模型比较:

Web服务器要为用户提供服务,必须以某种方式,工作在某个套接字上。一般Web服务器在处理用户请求是,一般有如下三种方式可选择:多进程方式、多线程方式、异步方式。**多进程方式:**为每个请求启动一个进程来处理。由于在操作系统中,生成进程、销毁进程、进程间切换都很消耗CPU和内存,当负载高是,性能会明显降低。**优点: 稳定性!**由于采用独立进程处理独立请求,而进程之间是独立的,单个进程问题不会影响其他进程,因此稳定性最好。**缺点: 资源占用!**当请求过大时,需要大量的进程处理请求,进程生成、切换开销很大,而且进程间资源是独立的,造成内存重复利用。**多线程方式:**一个进程中用多个线程处理用户请求。由于线程开销明显小于进程,而且部分资源还可以共享,因此效率较高。**优点:开销较小!**线程间部分数据是共享的,且线程生成与线程间的切换所需资源开销比进程间切换小得多。**缺点:稳定性!**线程切换过快可能造成线程抖动,且线程过多会造成服务器不稳定。**异步方式:**使用非阻塞方式处理请求,是三种方式中开销最小的。但异步方式虽然效率高,但要求也高,因为多任务之间的调度如果出现问题,就可能出现整体故障,因此使用异步工作的,一般是一些功能相对简单,但却符合服务器任务调度、且代码中没有影响调度的错误代码存在的程序。**优点:性能最好!**一个进程或线程处理多个请求,不需要额外开销,性能最好,资源占用最低。**缺点:稳定性!**某个进程或线程出错,可能导致大量请求无法处理,甚至导致整个服务宕机。

2.2 一个Web请求的处理过程:

技术分享

1客户发起情况到服务器网卡;

2服务器网卡接受到请求后转交给内核处理;

3内核根据请求对应的套接字,将请求交给工作在用户空间的Web服务器进程

4Web服务器进程根据用户请求,向内核进行系统调用,申请获取相应资源(如index.html)

5内核发现web服务器进程请求的是一个存放在硬盘上的资源,因此通过驱动程序连接磁盘

6内核调度磁盘,获取需要的资源

7内核将资源存放在自己的缓冲区中,并通知Web服务器进程

8Web服务器进程通过系统调用取得资源,并将其复制到进程自己的缓冲区中

9Web服务器进程形成响应,通过系统调用再次发给内核以响应用户请求

10内核将响应发送至网卡

11网卡发送响应给用户

通过这样的一个复杂过程,一次请求就完成了。简单来说就是:用户请求-->送达到用户空间-->系统调用-->内核空间-->内核到磁盘上读取网页资源->返回到用户空间->响应给用户。上述简单的说明了一下,客户端向Web服务请求过程,在这个过程中,有两个I/O过程,一个就是客户端请求的网络I/O,另一个就是Web服务器请求页面的磁盘I/O。 下面我们就来说说Linux的I/O模型。

三、各种I/O模型详解

通过上面的对连接的处理分析,我们知道工作在用户空间的web服务器进程是无法直接操作IO的,需要通过系统调用进行,其关系如下:技术分享

即进程向内核进行系统调用申请IO,内核将资源从IO调度到内核的buffer中(wait阶段),内核还需将数据从内核buffer中复制(copy阶段)到web服务器进程所在的用户空间,才算完成一次IO调度。这几个阶段都是需要时间的。根据wait和copy阶段的处理等待的机制不同,可将I/O动作分为如下五种模式:阻塞I/O非阻塞I/OI/O复用(select和poll)信号(事件)驱动I/O(SIGIO)异步I/O(aio)

3.1 I/O模型简介

这里有必要先解释一下阻塞、非阻塞,同步、异步、I/O的概念。3.1.1 阻塞和非阻塞:阻塞和非阻塞指的是执行一个操作是等操作结束再返回,还是马上返回。比如餐馆的服务员为用户点菜,当有用户点完菜后,服务员将菜单给后台厨师,此时有两种方式:第一种:就在出菜窗口等待,直到厨师炒完菜后将菜送到窗口,然后服务员再将菜送到用户手中;第二种:等一会再到窗口来问厨师,某个菜好了没?如果没有先处理其他事情,等会再去问一次;第一种就是阻塞方式,第二种则是非阻塞的。

3.1.2 同步和异步:

同步和异步又是另外一个概念,它是事件本身的一个属性。还拿前面点菜为例,服务员直接跟厨师打交道,菜出来没出来,服务员直接指导,但只有当厨师将 菜送到服务员手上,这个过程才算正常完成,这就是同步的事件。同样是点菜,有些餐馆有专门的传菜人员,当厨师炒好菜后,传菜员将菜送到传菜窗口,并通知服 务员,这就变成异步的了。其实异步还可以分为两种:带通知的和不带通知的。前面说的那种属于带通知的。有些传菜员干活可能主动性不是很够,不会主动通知 你,你就需要时不时的去关注一下状态。这种就是不带通知的异步。对于同步的事件,你只能以阻塞的方式去做。而对于异步的事件,阻塞和非阻塞都是可以的。非阻塞又有两种方式:主动查询和被动接收消息。被动不意味着 一定不好,在这里它恰恰是效率更高的,因为在主动查询里绝大部分的查询是在做无用功。对于带通知的异步事件,两者皆可。而对于不带通知的,则只能用主动查 询。

3.1.3 全异步I/O

回到I/O,不管是I还是O,对外设(磁盘)的访问都可以分成请求和执行两个阶段。请求就是看外设的状态信息(比如是否准备好了),执行才是真正的 I/O操作。在Linux 2.6之前,只有“请求”是异步事件,2.6之后才引入AIO(asynchronous I/O )把“执行”异步化。别看Linux/Unix是用来做服务器的,这点上比Windows落后了好多,IOCP(Windows上的AIO,效率极高)在Win2000上就有了。所以学linux的别老觉得Windows这里不好那里不好(Windows的多线程机制也由于linux)。

3.1.4 I/O的五种模型

根据以上分析,I/O可分为五种模型:

翻译 synchronous 同步的 asynchronous 异步的 blocking 阻塞的 Non-blocking 不闭塞的

技术分享

阻塞I/O:所有过程全阻塞

非阻塞I/O:如果没有数据buffer,则立即返回EWOULDBLOCK

I/O复用(select和poll):在wait和copy阶段分别阻塞

信号驱动I/O(SIGIO):在wait阶段不阻塞,但copy阶段阻塞(信号驱动I/O,即通知)

异步I/O(aio):完全无阻塞方式,当I/O完成是提供信号

Linux上的前四种I/O模型的“执行”阶段都是同步的,只有最后一种才做到了真正的全异步。第一种阻塞式是最原始的方法,也是最累的办法。当然累与不累要看针对谁。应用程序是和内核打交道的。对应用程序来说,这种方式是最累的,但对内核来说这种方式恰恰是最省事的。还拿点菜这事为例,你就是应用程序,厨师就是内核,如果你去了一直等着,厨师就省事了(不用同时处理其他服务员的菜)。当然现在计算机的设计,包括操作系统,越来越为终端用户考虑了, 为了让用户满意,内核慢慢的承担起越来越多的工作,IO模型的演化也是如此。

非阻塞I/O ,I/O复用,信号驱动式I/O其实都是非阻塞的,当然是针对“请求”这个阶段。非阻塞式是主动查询外设状态。I/O复用里的select,poll也是 主动查询,不同的是select和poll可以同时查询多个fd(文件句柄)的状态,另外select有fd个数的限制。epoll是基于回调函数的。信 号驱动式I/O则是基于信号消息的。这两个应该可以归到“被动接收消息”那一类中。最后就是伟大的AIO的出现,内核把什么事都干了,对上层应用实现了全 异步,性能最好,当然复杂度也最高。

3.2 各I/O模型详细介绍【本部分摘自独孤成博客】:

3.2.1 阻塞I/O

说明:应用程序调用一个IO函数,导致应用程序阻塞,等待数据准备好。 如果数据没有准备好,一直等待数据准备好了,从内核拷贝到用户空间,IO函数返回成功指示。这个不用多解释吧,阻塞套接字。下图是它调用过程的图示: (注,一般网络I/O都是阻塞I/O,客户端发出请求,Web服务器进程响应,在进程没有返回页面之前,这个请求会处于一直等待状态)技术分享3.2.2 非阻塞I/O我们把一个套接口设置为非阻塞就是告诉内核,当所请求的I/O操作无法完成时,不要将进程睡眠,而是返回一个错误。这样我们的I/O操作函数将不断 的测试数据是否已经准备好,如果没有准备好,继续测试,直到数据准备好为止。在这个不断测试的过程中,会大量的占用CPU的时间,所有一般Web服务器都 不使用这种I/O模型。具体过程如下图:技术分享3.2.3 I/O复用(select和poll)I/O复用模型会用到select或poll函数或epoll函数(Linux2.6以后的内核开始支持),这两个函数也会使进程阻塞,但是和阻塞 I/O所不同的的,这两个函数可以同时阻塞多个I/O操作。而且可以同时对多个读操作,多个写操作的I/O函数进行检测,直到有数据可读或可写时,才真正 调用I/O操作函数。具体过程如下图:技术分享3.2.4 信号驱动I/O(SIGIO)首先,我们允许套接口进行信号驱动I/O,并安装一个信号处理函数,进程继续运行并不阻塞。当数据准备好时,进程会收到一个SIGIO信号,可以在信号处理函数中调用I/O操作函数处理数据。具体过程如下图:技术分享

3.2.5 异步I/O(aio)

当一个异步过程调用发出后,调用者不能立刻得到结果。实际处理这个调用的部件在完成后,通过状态、通知和回调来通知调用者的输入输出操作。具体过程如下图:技术分享3.2.6 I/O 模型总结(如下图)技术分享从上图中我们可以看出,可以看出,越往后,阻塞越少,理论上效率也是最优。其五种I/O模型中,前三种属于同步I/O,后两者属于异步I/O。同步I/O:阻塞I/O

非阻塞I/O
I/O复用(select和poll)异步I/O:信号驱动I/O(SIGIO) (半异步)
异步I/O(aio) (真正的异步)异步 I/O 和 信号驱动I/O的区别:信号驱动 I/O 模式下,内核可以复制的时候通知给我们的应用程序发送SIGIO 消息。
异步 I/O 模式下,内核在所有的操作都已经被内核操作结束之后才会通知我们的应用程序。

3.3 Linux I/O模型的具体实现[转自孤城博客]

3.3.1 主要实现方式有以下几种:

  • select
  • poll
  • epoll
  • kqueue
  • /dev/poll
  • iocp

注,其中iocp是Windows实现的,select、poll、epoll是Linux实现的,kqueue是FreeBSD实现的,/dev /poll是SUN的Solaris实现的。select、poll对应第3种(I/O复用)模型,iocp对应第5种(异步I/O)模型,那么 epoll、kqueue、/dev/poll呢?其实也同select属于同一种模型,只是更高级一些,可以看作有了第4种(信号驱动I/O)模型的某 些特性,如callback机制。

3.3.2 为什么epoll、kqueue、/dev/poll比select高级?

答案是,他们无轮询。因为他们用callback取代了。想想看,当套接字比较多的时候,每次select()都要通过遍历FD_SETSIZE个 Socket来完成调度,不管哪个Socket是活跃的,都遍历一遍。这会浪费很多CPU时间。如果能给套接字注册某个回调函数,当他们活跃时,自动完成 相关操作,那就避免了轮询,这正是epoll、kqueue、/dev/poll做的。这样子说可能不好理解,那么我说一个现实中的例子,假设你在大学读 书,住的宿舍楼有很多间房间,你的朋友要来找你。select版宿管大妈就会带着你的朋友挨个房间去找,直到找到你为止。而epoll版宿管大妈会先记下 每位同学的房间号,你的朋友来时,只需告诉你的朋友你住在哪个房间即可,不用亲自带着你的朋友满大楼找人。如果来了10000个人,都要找自己住这栋楼的 同学时,select版和epoll版宿管大妈,谁的效率更高,不言自明。同理,在高并发服务器中,轮询I/O是最耗时间的操作之一,select、 epoll、/dev/poll的性能谁的性能更高,同样十分明了。

3.3.3 Windows or nix (IOCP or kqueue、epoll、/dev/poll)?

诚然,Windows的IOCP非常出色,目前很少有支持asynchronous I/O的系统,但是由于其系统本身的局限性,大型服务器还是在UNIX下。而且正如上面所述,kqueue、epoll、/dev/poll 与 IOCP相比,就是多了一层从内核copy数据到应用层的阻塞,从而不能算作asynchronous I/O类。但是,这层小小的阻塞无足轻重,kqueue、epoll、/dev/poll 已经做得很优秀了。

3.3.4 总结一些重点

只有IOCP(windows实现)是asynchronous I/O,其他机制或多或少都会有一点阻塞。select(Linux实现)低效是因为每次它都需要轮询。但低效也是相对的,视情况而定,也可通过良好的设计改善epoll(Linux实现)、kqueue(FreeBSD实现)、/dev/poll(Solaris实现)是Reacor模式,IOCP是Proactor模式。Apache 2.2.9之前只支持select模型,2.2.9之后支持epoll模型Nginx 支持epoll模型Java nio包是select模型

四、Apache Httpd的工作模式

4.1 apache三种工作模式

我们都知道Apache有三种工作模块,分别为prefork、worker、event。prefork:多进程,每个请求用一个进程响应,这个过程会用到select机制来通知。worker:多线程,一个进程可以生成多个线程,每个线程响应一个请求,但通知机制还是select不过可以接受更多的请求。event:基于异步I/O模型,一个进程或线程,每个进程或线程响应多个用户请求,它是基于事件驱动(也就是epoll机制)实现的。

4.2 prefork的工作原理

如果不用“--with-mpm”显式指定某种MPM,prefork就是Unix平台上缺省的MPM.它所采用的预派生子进程方式也是 Apache1.3中采用的模式。prefork本身并没有使用到线程,2.0版使用它是为了与1.3版保持兼容性;另一方面,prefork用单独的子 进程来处理不同的请求,进程之间是彼此独立的,这也使其成为最稳定的MPM之一。4.3 worker的工作原理相对于prefork,worker是2.0版中全新的支持多线程和多进程混合模型的MPM。由于使用线程来处理,所以可以处理相对海量的请求,而 系统资源的开销要小于基于进程的服务器。但是,worker也使用了多进程,每个进程又生成多个线程,以获得基于进程服务器的稳定性,这种MPM的工作方 式将是Apache2.0的发展趋势。4.4 event 基于事件机制的特性一个进程响应多个用户请求,利用callback机制,让套接字复用,请求过来后进程并不处理请求,而是直接交由其他机制来处理,通过epoll机 制来通知请求是否完成;在这个过程中,进程本身一直处于空闲状态,可以一直接收用户请求。可以实现一个进程程响应多个用户请求。支持持海量并发连接数,消 耗更少的资源。

五、如何提高Web服务器的并发连接处理能力

有几个基本条件:基于线程,即一个进程生成多个线程,每个线程响应用户的每个请求。基于事件的模型,一个进程处理多个请求,并且通过epoll机制来通知用户请求完成。基于磁盘的AIO(异步I/O)支持mmap内存映射,mmap传统的web服务器,进行页面输入时,都是将磁盘的页面先输入到内核缓存中,再由内核缓存中复制一份到web服务 器上,mmap机制就是让内核缓存与磁盘进行映射,web服务器,直接复制页面内容即可。不需要先把磁盘的上的页面先输入到内核缓存去。刚好,Nginx 支持以上所有特性。所以Nginx官网上说,Nginx支持50000并发,是有依据的。

六、Nginx优异之处

6.1 简介

传统上基于进程或线程模型架构的web服务通过每进程或每线程处理并发连接请求,这势必会在网络和I/O操作时产生阻塞,其另一个必然结果则是对内 存或CPU的利用率低下。生成一个新的进程/线程需要事先备好其运行时环境,这包括为其分配堆内存和栈内存,以及为其创建新的执行上下文等。这些操作都需 要占用CPU,而且过多的进程/线程还会带来线程抖动或频繁的上下文切换,系统性能也会由此进一步下降。另一种高性能web服务器/web服务器反向代 理:Nginx(Engine X),nginx的主要着眼点就是其高性能以及对物理计算资源的高密度利用,因此其采用了不同的架构模型。受启发于多种操作系统设计中基于“事件”的高级 处理机制,nginx采用了模块化、事件驱动、异步、单线程及非阻塞的架构,并大量采用了多路复用及事件通知机制。在nginx中,连接请求由为数不多的 几个仅包含一个线程的进程worker以高效的回环(run-loop)机制进行处理,而每个worker可以并行处理数千个的并发连接及请求。

6.2 Nginx 工作原理

Nginx会按需同时运行多个进程:一个主进程(master)和几个工作进程(worker),配置了缓存时还会有缓存加载器进程(cache loader)和缓存管理器进程(cache manager)等。所有进程均是仅含有一个线程,并主要通过“共享内存”的机制实现进程间通信。主进程以root用户身份运行,而worker、 cache loader和cache manager均应以非特权用户身份运行。主进程主要完成如下工作:读取并验正配置信息;创建、绑定及关闭套接字;启动、终止及维护worker进程的个数;无须中止服务而重新配置工作特性;控制非中断式程序升级,启用新的二进制程序并在需要时回滚至老版本;重新打开日志文件;编译嵌入式perl脚本;worker进程主要完成的任务包括:接收、传入并处理来自客户端的连接;提供反向代理及过滤功能;nginx任何能完成的其它任务;注:如果负载以CPU密集型应用为主,如SSL或压缩应用,则worker数应与CPU数相同;如果负载以IO密集型为主,如响应大量内容给客户端,则worker数应该为CPU个数的1.5或2倍。

6.3 Nginx 架构

Nginx的代码是由一个核心和一系列的模块组成, 核心主要用于提供Web Server的基本功能,以及Web和Mail反向代理的功能;还用于启用网络协议,创建必要的运行时环境以及确保不同的模块之间平滑地进行交互。不过, 大多跟协议相关的功能和某应用特有的功能都是由nginx的模块实现的。这些功能模块大致可以分为事件模块、阶段性处理器、输出过滤器、变量处理器、协 议、upstream和负载均衡几个类别,这些共同组成了nginx的http功能。事件模块主要用于提供OS独立的(不同操作系统的事件机制有所不同) 事件通知机制如kqueue或epoll等。协议模块则负责实现nginx通过http、tls/ssl、smtp、pop3以及imap与对应的客户端 建立会话。在Nginx内部,进程间的通信是通过模块的pipeline或chain实现的;换句话说,每一个功能或操作都由一个模块来实现。例如,压 缩、通过FastCGI或uwsgi协议与upstream服务器通信,以及与memcached建立会话等。

6.4 Nginx 基础功能

处理静态文件,索引文件以及自动索引;反向代理加速(无缓存),简单的负载均衡和容错;FastCGI,简单的负载均衡和容错;模块化的结构。过滤器包括gzipping, byte ranges, chunked responses, 以及 SSI-filter 。在SSI过滤器中,到同一个 proxy 或者 FastCGI 的多个子请求并发处理;SSL 和 TLS SNI 支持;

6.5 Nginx IMAP/POP3 代理服务功能

使用外部 HTTP 认证服务器重定向用户到 IMAP/POP3 后端;使用外部 HTTP 认证服务器认证用户后连接重定向到内部的 SMTP 后端;认证方法:POP3: POP3 USER/PASS, APOP, AUTH LOGIN PLAIN CRAM-MD5;IMAP: IMAP LOGIN;SMTP: AUTH LOGIN PLAIN CRAM-MD5;SSL 支持;在 IMAP 和 POP3 模式下的 STARTTLS 和 STLS 支持;

6.6 Nginx 支持的操作系统

FreeBSD 3.x, 4.x, 5.x, 6.x i386; FreeBSD 5.x, 6.x amd64;Linux 2.2, 2.4, 2.6 i386; Linux 2.6 amd64;Solaris 8 i386; Solaris 9 i386 and sun4u; Solaris 10 i386;MacOS X (10.4) PPC;Windows 编译版本支持 windows 系列操作系统;

6.7 Nginx 结构与扩展

一个主进程和多个工作进程,工作进程运行于非特权用户;kqueue (FreeBSD 4.1+), epoll (Linux 2.6+), rt signals (Linux 2.2.19+), /dev/poll (Solaris 7 11/99+), select, 以及 poll 支持;kqueue支持的不同功能包括 EV_CLEAR, EV_DISABLE (临时禁止事件), NOTE_LOWAT, EV_EOF, 有效数据的数目,错误代码;sendfile (FreeBSD 3.1+), sendfile (Linux 2.2+), sendfile64 (Linux 2.4.21+), 和 sendfilev (Solaris 8 7/01+) 支持;输入过滤 (FreeBSD 4.1+) 以及 TCP_DEFER_ACCEPT (Linux 2.4+) 支持;10,000 非活动的 HTTP keep-alive 连接仅需要 2.5M 内存。最小化的数据拷贝操作;

6.8 Nginx 其他

HTTP功能基于IP 和名称的虚拟主机服务;Memcached 的 GET 接口;支持 keep-alive 和管道连接;灵活简单的配置;重新配置和在线升级而无须中断客户的工作进程;可定制的访问日志,日志写入缓存,以及快捷的日志回卷;4xx-5xx 错误代码重定向;基于 PCRE 的 rewrite 重写模块;基于客户端 IP 地址和 HTTP 基本认证的访问控制;PUT, DELETE, 和 MKCOL 方法;支持 FLV (Flash 视频);带宽限制;

6.9 为什么选择Nginx

在高连接并发的情况下,Nginx是Apache服务器不错的替代品: Nginx在美国是做虚拟主机生意的老板们经常选择的软件平台之一. 能够支持高达 50,000 个并发连接数的响应, 感谢Nginx为我们选择了 epoll and kqueue 作为开发模型。Nginx作为负载均衡服务器: Nginx 既可以在内部直接支持 Rails 和 PHP 程序对外进行服务, 也可以支持作为 HTTP代理 服务器对外进行服务. Nginx采用C进行编写, 不论是系统资源开销还是CPU使用效率都比 Perlbal 要好很多。作为邮件代理服务器: Nginx 同时也是一个非常优秀的邮件代理服务器(最早开发这个产品的目的之一也是作为邮件代理服务器), Last.fm 描述了成功并且美妙的使用经验.Nginx 是一个 [#installation 安装] 非常的简单 , 配置文件 非常简洁(还能够支持perl语法),Bugs 非常少的服务器: Nginx 启动特别容易, 并且几乎可以做到7*24不间断运行,即使运行数个月也不需要重新启动. 你还能够 不间断服务的情况下进行软件版本的升级 。Nginx 的诞生主要

命令

ubuntu

$ sudo apt-get install nginx

mac

$ brew install nginx

查看版本

nginx -v

开启服务

$ sudo nginx

停止服务

$ sudo nginx -s quit

重启

$ sudo nginx -s reload

线性筛

#include <stdio.h>
#define MAX_RANGE 10000 // 求出10000以内的素数
int prime[MAX_RANGE + 5] = {0}; // 初始值为0,代表没有被标记成合数
int main() {
    // i 枚举算法中的 M 值
    for (int i = 2; i <= MAX_RANGE; i++) {
        // 如果找到素数,就把素数放到素数表中
        if (!prime[i]) { prime[++prime[0]] = i; }
        // 从小到大遍历素数表, prime[j] 为第 j 个素数
        for (int j = 1; j <= prime[0]; j++) {
            if (i * prime[j] > MAX_RANGE) break;
            prime[i * prime[j]] = 1; // 标记 i * prime[j] 为合数
            // i 能整除 prime[j],说明 prime[j] == (i 中最小素数了)
            if (i % prime[j] == 0) break;
        }
    }
    int n;
    while (scanf("%d", &n) != EOF) {
        // 输出第 n 个素数
        printf("%d\n", prime[n]);
    }
    return 0;
} 

Vue源码+简单实现

测试

	<div id="app">
  </div>
<script>

var vue = new Vue({
      el: '#app',
      data: {
        message: 'Hello world',
        isShow: false
      },
      render () {
        return createElement(
          'div',
          {
            attrs: {
              'class': 'wrapper'
            }
          },
          [
            this.isShow
            ? createElement(
              'p',
              { 
                attrs: {
                  'class': 'inner'
                }
              },
              this.message
            )
            : createElement(
              'h1',
              { 
                attrs: {
                  'class': 'inner'
                }
              },
              'Hello world'
            )
          ]
        )
      }
    })
  
    // test
    setTimeout(function () {
      vue.isShow = true;
    }, 1000)

    setTimeout(function () {
      vue.message = 'Hello';
    }, 2000)
  
    setTimeout(function () {
      vue.isShow = false;
    }, 3000)
     
    setTimeout(function () {
      vue.message = "HHHHHH";
    }, 4000)

    setTimeout(function () {
      vue.isShow = true;
    }, 5000)
    setTimeout(function () {
      vue.isShow = false;
    }, 6000)

</script>
  // 将Vue源码进行抽离,实现简单Vue功能
  // Vue模版解析

  // defineReactive
  

  function defineReactive (obj, key, val) {
    var dep = new Dep();    //列表
    Object.defineProperty(obj, key, {
      get: function () {
        if (Dep.target) {
          Dep.target.addDep(dep);
        }
        return val
      },
      set: function (newVal) {
        if (newVal === val) return;
        val = newVal;
        dep.notify();
      }
    })
  }


  function observe (obj) {
    for (var key in obj) {
      defineReactive(obj, key, obj[key])   // 循环将所有对象进行绑定

    }
  }

  var uid$1 = 0;
//传说中的观察者列表
  function Dep () {
    this.subs = [];
    this.id = uid$1++;
  }

  Dep.target = null;

  Dep.prototype.addSub = function (sub) {
    this.subs.push(sub)
  }

  Dep.prototype.notify = function () {
    var subs = this.subs;
    for (var i = 0, l = subs.length; i < l; i++) {
      subs[i].update()
    }
  }

  function Watcher (vm, expOrFn, cb) {
    this.vm = vm;
    this.getter = expOrFn;
    this.cb = cb;
    this.depIds = [];
    this.value = this.get();
  }

  Watcher.prototype.get = function () {
    Dep.target = this; /* ! */
    var value = this.getter.call(this.vm);
    Dep.target = null;
    return value
  }

  Watcher.prototype.update = function () {
    var value = this.get();
    if (this.value !== value) {
      var oldValue = this.value;
      this.value = value;
      this.cb.call(this.vm, value, oldValue);
    }
  }

  Watcher.prototype.addDep = function (dep) {
    var id = dep.id;
    // to avoid depending the watcher to the same dep more than once
    if (this.depIds.indexOf(id) === -1) {
      this.depIds.push(id);
      dep.addSub(this);
    }
  }

  function vnode (tag, data, children, text, elm) {
    this.tag = tag;
    this.data = data;
    this.children = children;
    this.text = text;
    this.elm = elm;
  }

  function normalizeChildren (children) {
    if (typeof children === 'string') {
      return [createTextVNode(children)]
    }
    return children
  }

  function createTextVNode (val) {
    return new vnode(undefined, undefined, undefined, String(val))
  }

  function createElement (tag, data, children) {
    return new vnode(tag, data, normalizeChildren(children), undefined, undefined);
  }

  function createElm (vnode) {
    var tag = vnode.tag;
    var data = vnode.data;
    var children = vnode.children;

    if (tag !== undefined) {
      vnode.elm = document.createElement(tag);

      if (data.attrs !== undefined) {
        var attrs = data.attrs;
        for (var key in attrs) {
          vnode.elm.setAttribute(key, attrs[key])
        }
      }

      if (children) {
        createChildren(vnode, children)
      }
    } else {
      vnode.elm = document.createTextNode(vnode.text);
    }

    return vnode.elm;
  }

  function createChildren (vnode, children) {
    for (var i = 0; i < children.length; ++i) {
      vnode.elm.appendChild(createElm(children[i]));
    }
  }

  function sameVnode (vnode1, vnode2) {
    return vnode1.tag === vnode2.tag
  }

  function emptyNodeAt (elm) {
    return new vnode(elm.tagName.toLowerCase(), {}, [], undefined, elm)
  }

  function patchVnode (oldVnode, vnode) {
    var elm = vnode.elm = oldVnode.elm;
    var oldCh = oldVnode.children;
    var ch = vnode.children;

    if (!vnode.text) {
      if (oldCh && ch) {
        updateChildren(oldCh, ch);
      }
    } else if (oldVnode.text !== vnode.text) {
      elm.textContent = vnode.text;
    }
  }

  function updateChildren (oldCh, newCh) {
    // assume that every element node has only one child to simplify our diff algorithm
    if (sameVnode(oldCh[0], newCh[0])) {
      patchVnode(oldCh[0], newCh[0])
    } else {
      patch(oldCh[0], newCh[0])
    }
  }

  function patch (oldVnode, vnode) {
    var isRealElement = oldVnode.nodeType !== undefined; // virtual node has no `nodeType` property
    if (!isRealElement && sameVnode(oldVnode, vnode)) {
      patchVnode(oldVnode, vnode);
    } else {
      if (isRealElement) {
        oldVnode = emptyNodeAt(oldVnode);
      }
      var elm = oldVnode.elm;
      var parent = elm.parentNode;

      createElm(vnode);

      parent.insertBefore(vnode.elm, elm);
      parent.removeChild(elm);
    }

    return vnode.elm
  }

// 测试




  function initData (vm) {
    var data = vm.$data = vm.$options.data;
    var keys = Object.keys(data);
    var i = keys.length
    // 就是把所有属性进行比案例
    // proxy data so you can use `this.key` directly other than `this.$data.key`
    while (i--) {
      proxy(vm, keys[i])
    }

    observe(data)
  }

  function proxy (vm, key) {
    Object.defineProperty(vm, key, {
      configurable: true,
      enumerable: true,
      get: function () {
        return vm.$data[key]
      },
      set: function (val) {
        vm.$data[key] = val
      }
    })
  }

  function Vue (options) {   //拿到new Vue里面的对象拿出来
    var vm = this;
    vm.$options = options;
    initData(vm);
    vm.mount(document.querySelector(options.el))
  }

  

  Vue.prototype.mount = function (el) {
    var vm = this;
    vm.$el = el;
    new Watcher(vm, function () {
      vm.update(vm.render());
    });
  }

  Vue.prototype.update = function (vnode) {
    var vm = this;
    var prevVnode = vm._vnode;
    vm._vnode = vnode;
    if (!prevVnode) {
      vm.$el = vm.patch(vm.$el, vnode);
    } else {
      vm.$el = vm.patch(prevVnode, vnode);
    }
  }

  Vue.prototype.patch = patch;

  Vue.prototype.render = function () {   //render函数渲染功能
    var vm = this;
    return vm.$options.render.call(vm)
  }


  

欧拉第八题Largest product in a series

可以暴力,如果不暴力,有0直接跳过

#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include "008.h"
int main() {
    int64_t ans = 1, zero = 0, maxN = 0;
    for (int32_t i = 0; i < 1000; ++i) {
        if (a[i] != '0') {
            ans *= a[i] - '0';
        } else {
            ++zero;
        }
        if (i >= 13) {
            if (a[i - 13] != '0') {
                ans /= a[i - 13] - '0';
            } else {
                --zero;
            }
        }
        if (zero == 0 && ans > maxN) maxN = ans;
    }
    printf("%"PRId64"\n",maxN);
    return 0;
}

大数相加C语言版

大数相加C

/*************************************************************************
	> File Name: BigData.c
	> Author: 
	> Mail: 
	> Created Time: 一  4/23 16:20:30 2018
 ************************************************************************/

#include<stdio.h>
#include<string.h>
int main(){
    int sum[200]={0};
    char arr[200];
    while(~scanf("%s",arr)){
        int len = strlen(arr);
        for(int i = len;i>0;i--){
            
            sum[i] += arr[len-i] - '0';
        }
        
        for(int i = 0;i<199;i++){
            sum[i+1]+=sum[i]/10;
            sum[i]=sum[i]%10;
        }
        int lock = 0;

        for(int i = 199;i>0;i--){
           if(sum[i]!=0){
                lock = 1;
            }
            if(lock){
                printf("%d",sum[i]);
            }
        }
        printf("\n");
    }
}

大数相加C语言优化版

#include<stdio.h>
#include<string.h>
int main(){
    int sum[200]={0};
    char arr[200];
    while(~scanf("%s",arr)){
        int len = strlen(arr);
        for(int i = len;i>0;i--){            
           sum[i] += arr[len-i] - '0';
        }
     
    }
    
    for(int i = 0;i<199;i++){
        sum[i+1]+=sum[i]/10;
        sum[i]=sum[i]%10;
    }
    int lock = 0;

    for(int i = 199;i>0;i--){
       if(sum[i]!=0){
            lock = 1;
        }
        if(lock){
            printf("%d",sum[i]);
        }
    }
    printf("\n");
}

Object.keys解析

Object.keys用法

// by mdn
if (!Object.keys) {
  Object.keys = (function () {
    var hasOwnProperty = Object.prototype.hasOwnProperty,
        hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'),
        dontEnums = [
          'toString',
          'toLocaleString',
          'valueOf',
          'hasOwnProperty',
          'isPrototypeOf',
          'propertyIsEnumerable',
          'constructor'
        ],
        dontEnumsLength = dontEnums.length;

    return function (obj) {
      if (typeof obj !== 'object' && typeof obj !== 'function' || obj === null) throw new TypeError('Object.keys called on non-object');

      var result = [];

      for (var prop in obj) {
        if (hasOwnProperty.call(obj, prop)) result.push(prop);
      }

      if (hasDontEnumBug) {
        for (var i=0; i < dontEnumsLength; i++) {
          if (hasOwnProperty.call(obj, dontEnums[i])) result.push(dontEnums[i]);
        }
      }
      return result;
    }
  })()
};

HTTP网络基础

使用HTTP协议访问Web

经典问题:当我们从浏览器输入一个url发生了什么?👇

用户本地域名服务器,你知道www.google.com是多少么

本地域名服务器说:等会兄弟,我去问问根域名服务器COM顶级域名服务器

根域名服务器:兄弟我也不知道,但是你可以问COM顶级域名服务器问问,他应该知道

COM顶级域名服务器:兄弟我也不知道,但是你可以问google.com域名服务器问问,他应该知道

google.com域名服务器:兄弟我知道,他是64.233.189.104

也就是说他的解析顺序是

. → .com. → google.com. → www.google.com.

DNS负载均衡

不知道大家有没有思考过一个问题: DNS返回的IP地址是否每次都一样?如果每次都一样是否说明你请求的资源都位于同一台机器上面,那么这台机器需要多高的性能和储存才能满足亿万请求呢?其实真实的互联网世界背后存在成千上百台服务器,大型的网站甚至更多。但是在用户的眼中,它需要的只是处理他的请求,哪台机器处理请求并不重要。DNS可以返回一个合适的机器的IP给用户,例如可以根据每台机器的负载量,该机器离用户地理位置的距离等等,这种过程就是DNS负载均衡,又叫做DNS重定向。大家耳熟能详的CDN(Content Delivery Network)就是利用DNS的重定向技术,DNS服务器会返回一个跟用户最接近的点的IP地址给用户,CDN节点的服务器负责响应用户的请求,提供所需的内容。

TCP连接

HTTP的长连接和短连接本质上是TCP长连接和短连接。HTTP属于应用层协议,在传输层使用TCP协议,在网络层使用IP协议。IP协议主要解决网络路由和寻址问题,TCP协议主要解决如何在IP层之上可靠的传递数据包,使在网络上的另一端收到发端发出的所有包,并且顺序与发出顺序一致。TCP有可靠,面向连接的特点。

发送HTTP请求

HTTPS协议

我不知道把HTTPS放在这个部分是否合适,但是放在这里好像又说的过去。HTTP报文是包裹在TCP报文中发送的,服务器端收到TCP报文时会解包提取出HTTP报文。但是这个过程中存在一定的风险,HTTP报文是明文,如果中间被截取的话会存在一些信息泄露的风险。那么在进入TCP报文之前对HTTP做一次加密就可以解决这个问题了。HTTPS协议的本质就是HTTP + SSL(or TLS)。在HTTP报文进入TCP报文之前,先使用SSL对HTTP报文进行加密。从网络的层级结构看它位于HTTP协议与TCP协议之间。

http HTTP→TCP→IP https HTTP→SSL或TLS→TCP→IP

HTTP

其实这部分又可以称为前端工程师眼中的HTTP,它主要发生在客户端。发送HTTP请求的过程就是构建HTTP请求报文并通过TCP协议中发送到服务器指定端口(HTTP协议80/8080, HTTPS协议443)。HTTP请求报文是由三部分组成: 请求行, 请求报头请求正文

服务器处理请求并返回HTTP报文

HTTP请求报文是由三部分组成: 请求行, 请求报头请求正文组成

请求行:

GET index.html HTTP/1.1

例如:GET, POST, PUT, DELETE, OPTIONS, HEAD。

请求报头:

请求报头允许客户端向服务器传递请求的附加信息和客户端自身的信息。 PS: 客户端不一定特指浏览器,有时候也可使用Linux下的CURL命令以及HTTP客户端测试工具等。 常见的请求报头有: Accept, Accept-Charset, Accept-Encoding, Accept-Language, Content-Type, Authorization, Cookie, User-Agent等。

请求正文:

当使用POST, PUT等方法时,通常需要客户端向服务器传递数据。这些数据就储存在请求正文中。在请求包头中有一些与请求正文相关的信息,例如: 现在的Web应用通常采用Rest架构,请求的数据格式一般为json。这时就需要设置Content-Type: application/json。

服务器处理请求并返回HTTP报文:

自然而然这部分对应的就是后端工程师眼中的HTTP。后端从在固定的端口接收到TCP报文开始,这一部分对应于编程语言中的socket。它会对TCP连接进行处理,对HTTP协议进行解析,并按照报文格式进一步封装成HTTP Request对象,供上层使用。这一部分工作一般是由Web服务器去进行,我使用过的Web服务器有Tomcat, Jetty和Netty等等。

状态码

状态码是由3位数组成,第一个数字定义了响应的类别,且有五种可能取值:

  • 1xx:指示信息–表示请求已接收,继续处理。
  • 2xx:成功–表示请求已被成功接收、理解、接受。
  • 3xx:重定向–要完成请求必须进行更进一步的操作。
  • 4xx:客户端错误–请求有语法错误或请求无法实现。
  • 5xx:服务器端错误–服务器未能实现合法的请求。 平时遇到比较常见的状态码有:200, 204, 301, 302, 304, 400, 401, 403, 404, 422, 500(分别表示什么请自行查找)。
响应报头

常见的响应报头字段有: Server, Connection...。

响应报文

服务器返回给浏览器的文本信息,通常HTML, CSS, JS, 图片等文件就放在这一部分。

浏览器解析渲染页面

浏览器在收到HTML,CSS,JS文件后,会进行浏览器解析,我会在以后讲解webkit内核的渲染原理

以上是一个经典问题比较含糊的回答👆

HTTP0.9/1.0/1.1协议之间的区别

HTTP 0.9

HTTP/0.9是第一个版本的HTTP协议,已过时。它的组成极其简单,只允许客户端发送GET这一种请求,且不支持请求头。由于没有协议头,造成了HTTP/0.9协议只支持一种内容,即纯文本。不过网页仍然支持用HTML语言格式化,同时无法插入图片。

HTTP/0.9具有典型的无状态性,每个事务独立进行处理,事务结束时就释放这个连接。由此可见,HTTP协议的无状态特点在其第一个版本0.9中已经成型。一次HTTP/0.9的传输首先要建立一个由客户端到Web服务器的TCP连接,由客户端发起一个请求,然后由Web服务器返回页面内容,然后连接会关闭。如果请求的页面不存在,也不会返回任何错误码。

HTTP 1.0

HTTP协议的第二个版本,第一个在通讯中指定版本号的HTTP协议版本,至今仍被广泛采用。相对于HTTP/0.9增加了如下主要特性:

  • 请求与响应支持头域
  • 响应对象以一个响应状态行开始
  • 响应对象不只限于超文本
  • 开始支持客户端通过POST方法向Web服务器提交数据,支持GET、HEAD、POST方法
  • 支持长连接(但默认还是使用短连接),缓存机制,以及身份认证相关

HTTP 1.1

目前使用最广泛的协议版本。主流的HTTP协议版本,新增了以下内容:

  1. 默认为长连接

    HTTP 1.1支持长连接(PersistentConnection)和请求的流水线(Pipelining)处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP1.1中默认开启Connection:keep-alive,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点。

  2. 提供了范围请求功能(宽带优化)

    HTTP1.0中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,HTTP1.1则在请求头引入了range头域,它允许只请求资源的某个部分,即返回码是206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。这是支持文件断点续传的基础。

  3. 提供了虚拟主机的功能(HOST域)

    在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误(400 Bad Request)。

  4. 多了一些缓存处理字段

    HTTP/1.1在1.0的基础上加入了一些cache的新特性,引入了实体标签,一般被称为e-tags,新增更为强大的Cache-Control头。

  5. 错误通知的管理

    在HTTP1.1中新增了24个错误状态响应码,如409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。

HTTP 2.0

  1. 二进制分帧

    HTTP 2.0 的所有帧都采用二进制编码

    • 帧:客户端与服务器通过交换帧来通信,帧是基于这个新协议通信的最小单位。
    • 消息:是指逻辑上的 HTTP 消息,比如请求、响应等,由一或多个帧组成。
    • 流:流是连接中的一个虚拟信道,可以承载双向的消息;每个流都有一个唯一的整数标识符(1、2 … N);
  2. 多路复用

    多路复用允许同时通过单一的HTTP/2.0 连接发起多重的请求-响应消息。有了新的分帧机制后,HTTP/2.0不再依赖多个TCP 连接去处理更多并发的请求。每个数据流都拆分成很多互不依赖的帧,而这些帧可以交错(乱序发送),还可以分优先级。最后再在另一端根据每个帧首部的流标识符把它们重新组合起来。HTTP 2.0 连接都是持久化的,而且客户端与服务器之间也只需要一个连接(每个域名一个连接)即可。

  3. 头部压缩

    HTTP/1.1 的首部带有大量信息,而且每次都要重复发送。HTTP/2.0 要求通讯双方各自缓存一份首部字段表,从而避免了重复传输。

  4. 请求优先级

    浏览器可以在发现资源时立即分派请求,指定每个流的优先级,让服务器决定最优的响应次序。这样请求就不必排队了,既节省了时间,也最大限度地利用了每个连接。

  5. 服务端推送

    服务端推送能把客户端所需要的资源伴随着index.html一起发送到客户端,省去了客户端重复请求的步骤。正因为没有发起请求,建立连接等操作,所以静态资源通过服务端推送的方式可以极大地提升速度。

网络基础TCP/IP

TCP/IP协议族

计算机分成7层网络协议,

有一张特别容易理解的图👇

网络7层协议图

7层的协议官方介绍👇

应用层

与其它计算机进行通讯的一个应用,它是对应应用程序的通信服务的。例如,一个没有通信功能的字处理程序就不能执行通信的代码,从事字处理工作的程序员也不关心OSI的第7层。但是,如果添加了一个传输文件的选项,那么字处理器的程序员就需要实现OSI的第7层。示例:TELNET,HTTP,FTP,NFS,SMTP等。

应用层决定了像用户提供应用服务时通信的活动

表示层

这一层的主要功能是定义数据格式及加密。例如,FTP允许你选择以二进制或ASCII格式传输。如果选择二进制,那么发送方和接收方不改变文件的内容。如果选择ASCII格式,发送方将把文本从发送方的字符集转换成标准的ASCII后发送数据。在接收方将标准的ASCII转换成接收方计算机的字符集。示例:加密,ASCII等。

会话层

它定义了如何开始、控制和结束一个会话,包括对多个双向消息的控制和管理,以便在只完成连续消息的一部分时可以通知应用,从而使表示层看到的数据是连续的,在某些情况下,如果表示层收到了所有的数据,则用数据代表表示层。示例:RPC,SQL等。

传输层

这层的功能包括是否选择差错恢复协议还是无差错恢复协议,及在同一主机上对不同应用的数据流)的输入进行复用,还包括对收到的顺序不对的数据包的重新排序功能。示例:TCP,UDP,SPX。

网络层

这层对端到端的包传输进行定义,它定义了能够标识所有结点的逻辑地址,还定义了路由]实现的方式和学习的方式。为了适应最大传输单元长度小于包长度的传输介质,网络层还定义了如何将一个包分解成更小的包的分段方法。示例:IP,IPX等。

数据链路层

它定义了在单个链路上如何传输数据。这些协议与被讨论的各种介质有关。示例:ATM,FDDI等。

物理层

OSI的物理层规范是有关传输介质的特这些规范通常也参考了其他组织制定的标准。连接头、帧、帧的使用、电流、编码及光调制等都属于各种物理层规范中的内容。物理层常用多个规范完成对所有细节的定义。示例:Rj45,802.3等。

经典问题TCP和UDP的区别

TCP UDP
是否连接 面向连接 面向非连接
传输可靠性 可靠的 不可靠的
应用场合 传输大量的数据 少量数据
速度
场景 网页的浏览,文件的下载(不是迅雷那种),邮件的收发 实用性强,允许出错的场合,如即时通讯,QQ,视频语言方面

欧拉第七题10001st prime🔥

这题涉及到两种优秀的算法,不算传统算法,我们上来就应该想到素数筛和线性筛
素数筛(埃拉托斯特尼筛法),标记素数,重复筛选,
线性筛(欧拉筛法),标记合数,不重复筛选

素数筛版本

#include<stdio.h>
#define MAX 10000
int main(){
    int prem[MAX]={0};
    for(int i = 2;i<MAX;i++){
        for(int j=i*i;j<MAX;j+=i){
            prem[j] = 1;
        }
    }
    for(int i = 2;i<30;i++){
        if(!prem[i]){
            printf("%d",i);
        }
    }
}

线性筛版本

#include <stdio.h>
#include <inttypes.h>
#define MAX_RANGE 10000 // 求出10000以内的素数
int32_t prime[MAX_RANGE + 5] = {0}; // 初始值为0,代表没有被标记成合数
int32_t main() {
    // i 枚举算法中的 M 值
    for (int32_t i = 2; i <= MAX_RANGE; i++) {
        // 如果找到素数,就把素数放到素数表中
        if (!prime[i]) { prime[++prime[0]] = i; }
        // 从小到大遍历素数表, prime[j] 为第 j 个素数
        for (int32_t j = 1; j <= prime[0]; j++) {
            if (i * prime[j] > MAX_RANGE) break;
            prime[i * prime[j]] = 1; // 标记 i * prime[j] 为合数
            // i 能整除 prime[j],说明 prime[j] == (i 中最小素数了)
            if (i % prime[j] == 0) break;
        }
    }
    int32_t n;
    while (scanf("%d", &n) != EOF) {
        // 输出第 n 个素数
        printf("%d\n", prime[n]);
    }
    return 0;
}

斐波那契+大数相加

/*************************************************************************
	> File Name: fn.c
	> Author: 
	> Mail: 
	> Created Time: 日  4/22 19:46:51 2018
 ************************************************************************/

#include<stdio.h>
int main(){
    int f[3][1005] = {0,1,1},n = 2;
    f[1][0] = f[1][1] = 1;
    f[2][0] = f[2][1] = 1;

    while(f[n%3][0]<1000){
        n++;
        for(int i = 1;i<=f[(n+2)%3][0];i++)
        
        f[n%3][i] = f[(n+1)%3][i] + f[(n+2)%3][i];
        f[n%3][0] = f[(n+2)%3][0];
        for(int i = 1;i<=f[n%3][0];i++){
            if(f[n%3][i]<10)continue;
            f[n%3][i+1] +=f[(n%3)][i] /10;
            f[n%3][i]%=10;
            f[n%3][0]+=(i==f[n%3][0]);
        }
    }
    
    printf("%d\n",n);

    return 0;
}

欧拉第四题Largest palindrome product

最大的回文数
两位2位数相乘的最大回文数是9009 = 91×99。
查找由两个3位数相乘的最大回文数。

#include <stdio.h>
int check(int a) {
	int b = a, x = 0;
	while (a) {
		x = x * 10 + a % 10;
		a /= 10;
	}
	return b == x;
}
int main()
{
	int maxN = 0;
	for (int i = 100; i <= 999; ++i)
		for (int j = i; j <= 999; ++j)
			if (check(i * j) && i * j > maxN)
				maxN = i * j;
	printf("%d\n",maxN);
	return 0;
}

JavaScript帧动画

一般在安卓开发中会考虑到帧动画,前端也一样,安卓帧动画也解释的非常详细,总结一下,帧动画就是在连续的关键帧上分解动画,也就是在时间轴的每帧上绘制不同的内容,使其连续播放而形成动画.正如那种动漫其实都是一个画一个画画出来的,只不过每1秒可能就需要十张画.

原生 JS 实现帧动画库

所以我这次实现一个帧动画库

欧拉第十一题Largest product in a grid

#include <stdio.h>
#include <inttypes.h>
int32_t nums[35][35] = {0};
int32_t direct[4][2] = {0, 1, 1, 1, 1, 0, 1, -1};
int main() {
    for (int32_t i = 5; i <= 24; i++)
        for (int32_t j = 5; j <= 24; j++)
            scanf("%d", &nums[i][j]);
    int32_t p, ma = 0;
    for (int32_t i = 5; i <= 24; i++) {
        for (int32_t j = 5; j <= 24; j++) {
            for (int32_t k = 0; k < 4;k++) {
                p = 1;
                for (int32_t l = 0;l < 4; l++) {
                    p *= nums[i + l * direct[k][0]][j + l * direct[k][1]];
                }
                if (p > ma) ma = p;
            }
        }
    }
    printf("%d\n", ma);
    return 0;
}

C语言总结

C语言总结

floor 函数 下取整数
头文件 math.h
double floor

//判断大头小头
#include "stdio.h"

int test(){
	int a = 1;
	unsigned char *p = (unsigned char *)&a;
	return (*p) ^ 1;
}

int main(){
	printf("%d", test());
}

整数pow

int powint(int x,int y){
	int z=1;
	if(x){
		
		while (x--) {
		    z *= y;	
		}
		return z;
	}
    return 1;
}

inttypes.h简介

为啥用inttypes.h?

用inttypes.h代替long long因为有的编译器long long 不是真long long
用法

#include "inttypes.h"
int main(){
n =1000;
printf("%" PRId64"\n",n);
}

经典三栏布局

三栏布局(假设高度已知的话)

float解决方案

高度未知失效

    <section class="layout float">
        <article class="left-right-center">
            <style media="screen">
               .layout.float .left{
                  float: left;
                  width: 300px;
                  background: blue;
               }
               .layout.float .right{
                  float: right;
                  width: 300px;
                  background:blue;
               }
               .layout.float .center{
                  background:red;
               }       
            </style>
             <div class="left"></div>  
             <div class="right"></div>   
             <div class="center">
                 <h1>浮动解决方案</h1>
                 1.三栏
                 2.三栏
                 3.三滥
             </div>
             
        </article>
    </section>

绝对定位

高度未知失效

  <section class="layout absolute">
        <article class="left-center-right">
            <style media="screen">
                .layout.absolute .left-center-right>div{
                    position: absolute;

                }
                .layout.absolute .left{
                    left: 0;
                    width: 300px;
                    background: red;
                }
                .layout.absolute .center{
                    left: 300px;
                    right: 300px;
                    background: blue;
                }
                .layout.absolute .right{
                    right: 0;
                    width: 300px;
                    background: red;
                }
            </style>
             <div class="left"></div>  
             <div class="right"></div>   
             <div class="center">
                 <h1>绝对定位解决方案</h1>
                 1.三栏
                 2.三栏
                 3.三滥
             </div>
             
        </article>
    </section>

flexbox解决方案

  <section class="layout flex">
        <article class="left-center-right">
            <style media="screen">
                .layout.flex .left-center-right{
                  display: flex;
                }
                .layout.flex .left{
                    width: 300px;
                    background: red;
                }
                .layout.flex .right{
                    width: 300px;
                    background: red;
                }
                .layout.flex .center{
                    flex:1;
                    background: blue;
                }
            </style>
             <div class="left"></div>  
                
             <div class="center">
                 <h1>flex解决方案</h1>
                 1.三栏
                 2.三栏
                 3.三滥
             </div>
             <div class="right"></div>
             
        </article>
    </section>

表格布局

   <section class="layout table">
        <article class="left-center-right">
            <style media="screen">
              .layout.table  .left-center-right{
                  width: 100%;
                  display: table;
                  height: 100px;
              } 
              .layout.table .left-center-right>div{
                display: table-cell;
              }
              .layout.table .left{
                 width: 300px;
                 background: red;
              }
              .layout.table .center{
                 background: blue;
              }
              .layout.table .right{
                 width: 300px;
                 background: red;
              }
            </style>
             <div class="left"></div>  
                
             <div class="center">
                 <h1>表哥解决方案</h1>
                 1.三栏
                 2.三栏
                 3.三滥
             </div>
             <div class="right"></div>
             
        </article>
    </section>

网格布局

高度未知失效

网格布局新出的,兼容性一般,

   <section class="layout grid">
        <article class="left-center-right">
            <style media="screen">
              .layout.grid  .left-center-right{
                display: grid;
                width: 100%;
                grid-template-rows: 100px;
                grid-template-columns: 300px auto 300px;
              }
              .layout.grid .left{
                  background: red;
              }
              .layout.grid .center{
                  background: blue;
              }
              .layout.grid .right{
                  background: red;
              }

            </style>
             <div class="left"></div>  
                
             <div class="center">
                 <h1>网格解决方案</h1>
                 1.三栏
                 2.三栏
                 3.三滥
             </div>
             <div class="right"></div>
             
        </article>
    </section>

🔥欧拉计划

1.容斥原理

求出在1000里被3和5整除的数

思路1:

#include <stdio.h>
int main(){
    int sum = 0;
    for(int i = 0;i<1000;i++){
        if(i % 3 == 0){
             sum += i;
        }
        if(i % 5 == 0){
             sum += i;
        }
        if(i % 3 == 0&&i % 5 ==0){
             sum -=i;
        }
    }
}

思路2:

#include <stdio.h>
int main() {
    int sum = 0;
    for (int i = 0; i < 1000; i++) {
        if (i % 3 == 0 || i % 5 == 0)
            sum += i;
    }
    printf("%d\n", sum);
}

2.斐波那契

求出偶数项斐波那契不超过400万的和

思路1:

#include <stdio.h>
int main() {
	int f[10000]={0};
	f[1] = 1;
	f[2] = 2;
    int sum = 0;
	for(int i = 1;f[i]<=4000000;i++){
		f[i+2] = f[i+1] + f[i];
    }
	for(int i = 1;f[i]<=4000000;i++){
		if(f[i]%2==0){
            sum += f[i];
        }
	}
	  //  
	printf("%d\n",sum);
}

思路2:

#include <stdio.h>
int main() {
	int a, b, c, sum = 0;
	a = 1; b = 1;
	while (b < 4000000) {
		if (b % 2 == 0){
			sum += b;
		} 
		c = b;
		b = a + b;
		a = c;   
	}
	printf("%d\n", sum);
	return 0;
}

3.最大的最小公倍数

13195的最小公倍数是5,7,13和29。

数字600851475143的最大公倍数是?

思路:1

#include <stdio.h>
#define NUM 600851475143
int main() {
	long long num = NUM;
	long long maxl=0;
	for (int i = 2; i  <= num; ++i) {
        while (num%i==0) {
	        num/=i;
                 maxl = i;
        }
	}
	printf("%lld\n", maxl);
	return 0;
}

思路:2

#include <stdio.h>
#define NUM 600851475143
int main() {
    long long num = NUM;
    long long max_prime;
    for (long long i = 2; i * i <= NUM; ++i) {
        while (num % i == 0) {
            num /= i;
            max_prime = i;
        }
    }
    if (num != 1) max_prime = num;
    printf("%lld\n", max_prime);
    return 0;
}

4.最大的回文数

两位2位数相乘的最大回文数是9009 = 91×99。

查找由两个3位数相乘的最大回文数。

#include <stdio.h>
int check(int a) {
	int b = a, x = 0;
	while (a) {
		x = x * 10 + a % 10;
		a /= 10;
	}
	return b == x;
}
int main()
{
	int maxN = 0;
	for (int i = 100; i <= 999; ++i)
		for (int j = i; j <= 999; ++j)
			if (check(i * j) && i * j > maxN)
				maxN = i * j;
	printf("%d\n",maxN);
	return 0;
}

5.最小的倍数

#include <stdio.h>
#include <stdlib.h>
int gcd(long long a,long long b) {
	if (!b) return a;
	return gcd(b, a % b);
}
int main() {
	long long ans = 1;
	for (long long i = 1; i <= 20; i++) {
		ans *= i / gcd(i, ans);
	}
	printf("%lld\n", ans);
	return 0;
}

2520是可以被1到10中的每个数字整除的最小数字。

什么是可以被1到20的所有数字整除的最小正数?

6.总平方差

#include <stdio.h>
#include <stdlib.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;
}

7.第10001个素数

用素数筛方法

#include <stdio.h>
#define MAX_NUM 500000
int main(){
     int prem[MAX_NUM+10]={0};
     for(int i = 2;i * i < MAX_NUM;i++){
	    if(!prem[i]){
		    for(int j = i*i;j<MAX_NUM+5;j+=i){
			    prem[j] = 1;
		    }
        }
     }
     int sum = 0;
     for(int i = 2;i<MAX_NUM+5;i++){
	 if(!prem[i]){
		 sum++;
		if(sum == 10001){
			printf("%d",i);
			break;
	     }
	  }
   }
}

番外篇:

利用二分法查找立方,有bug,能正常运行

#include <stdio.h>
#include <math.h>
int main(int argc, char *argv[]) {
	int min = -100;
	int max = 100;
	int aim;
	scanf("%d",&aim);
	int ci = 0;
	int mid = 0;
		while (pow(mid,3)!=aim) {
		ci++;
        mid = (min+max)/2;
        if( pow(mid,3)>aim){
	       max=mid;
        }
        if(pow(mid,3)<aim){
	       min=mid;
        }
        if(pow(mid ,3)== aim){
	      printf("%d",mid);
        }
	}
}

8.

45三角形数,五边形数,六边形数(设计**)

牛顿迭代法45题

只需要判断五边形数和六边形数即可

#include "stdio.h"
#include "inttypes.h"
int is_penta(int64_t n){
	int64_t head = 1, tail = n,mid;
	while (head <= tail) {
		mid = (head + tail)>>1;
		int64_t value = mid*(3*mid-1)/2;
		if(value<0) printf("cnmd\n");
		if(value==n) return 1;
		if(value >n) tail = mid -1;
		else head = mid +1;
	}
	return 0;
}

int main (){
	int64_t n = 144;
	while (!is_penta(n*(2 * n-1)))++n; 
	printf("%" PRId64"\n",n*(2*n-1));
	}
	

升级方法

#include "stdio.h"
#include "inttypes.h"
int64_t Penta(int64_t n){
    return n* (3*n -1)/2;
}
int binary_search(int64_t n, int64_t (*func)(int64_t)){
	int64_t head = 1, tail = n,mid;
	while (head <= tail) {
		mid = (head + tail)>>1;
		int64_t value = func(mid);
		if(value<0) printf("cnmd\n");
		if(value==n) return 1;
		if(value >n) tail = mid -1;
		else head = mid +1;
	}
	return 0;
}

int main (){
	int64_t n = 144;
	
	while (!binary_search(n*(2 * n-1),Penta))++n; 
	printf("%" PRId64"\n",n*(2*n-1));
	}
	

升级方法测试

#include "stdio.h"
#include "inttypes.h"
int64_t Penta(int64_t n){
    return n* (3*n -1)/2;
}

int64_t Power2(int64_t n){
	return n*n;
}

int binary_search(int64_t n, int64_t (*func)(int64_t)){
	int64_t head = 1, tail = n,mid;
	while (head <= tail) {
		mid = (head + tail)>>1;
		int64_t value = func(mid);
		if(value<0) printf("cnmd\n");
		if(value==n) return 1;
		if(value >n) tail = mid -1;
		else head = mid +1;
	}
	return 0;
}

int main (){
	int64_t n = 144;
	while (!binary_search(n*(2 * n-1),Penta))++n; 
	printf("%" PRId64"\n",n*(2*n-1));
	}

欧拉第五题Smallest multiple

利用辗转相除法进行快速寻找gcd(最小公倍数)

#include <stdio.h>
#include <stdlib.h>
int gcd(long long a,long long b) {
	if (!b) return a;
	return gcd(b, a % b);
}
//gcd辗转取余
int main() {
	long long ans = 1;
	for (long long i = 1; i <= 20; i++) {
		ans *= i / gcd(i, ans);
	}
	printf("%lld\n", ans);
	return 0;
}

2520是可以被1到10中的每个数字整除的最小数字。
什么是可以被1到20的所有数字整除的最小正数?
此题可以吧ans当作一个大数,然后每次求大数和1,2,3,4,5,6的最小公倍数

欧拉第十题Summation of primes

素数筛直接+和

 #include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#define MAX_RANGE 2000000
int32_t prime[MAX_RANGE + 5] = {0};
int main() {
    int64_t sum = 0;
    for (int32_t i = 2; i <= MAX_RANGE; ++i) {
        if (!prime[i]) { prime[++prime[0]] = i; sum += i; }
        for (int32_t j = 1; j <= prime[0] && prime[j] * i <= MAX_RANGE; ++j) {
            prime[i * prime[j]] = 1;
            if (i % prime[j] == 0) break;
        }
    }
    printf("%"PRId64"\n",sum);
    return 0;
}

欧拉第三题Largest prime factor

最大的最小公倍数

13195的最小公倍数是5,7,13和29。

数字600851475143的最大公倍数是?

思路:1

#include <stdio.h>
#define NUM 600851475143
int main() {
	long long num = NUM;
	long long maxl=0;
	for (int i = 2; i  <= num; ++i) {
        while (num%i==0) {
	        num/=i;
                 maxl = i;
        }
	}
	printf("%lld\n", maxl);
	return 0;
}

思路:2

#include <stdio.h>
#define NUM 600851475143
int main() {
    long long num = NUM;
    long long max_prime;
    for (long long i = 2; i * i <= NUM; ++i) {
        while (num % i == 0) {
            num /= i;
            max_prime = i;
        }
    }
    if (num != 1) max_prime = num;
    printf("%lld\n", max_prime);
    return 0;
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.