CF786題解

来源:https://www.cnblogs.com/Call-me-Eric/archive/2023/11/30/17868050.html
-Advertisement-
Play Games

CF786 我不會告訴你鏈接在圖片里 CF786A CF786A題意 給出一個大小為 \(n\) 的環,點順時針從 \(1\to n\) 編號,兩個人(設為 \(0,1\))輪流移動其中的一個棋子。 對於第 \(opt\) 人,他能夠將這個棋子順時針移動 \(x\in S_{opt}\)(\(S_{ ...


CF786

Codeforces Round 406 (Div. 1)
我不會告訴你鏈接在圖片里

CF786A

CF786A

CF786A題意

給出一個大小為 \(n\) 的環,點順時針從 \(1\to n\) 編號,兩個人(設為 \(0,1\))輪流移動其中的一個棋子。
對於第 \(opt\) 人,他能夠將這個棋子順時針移動 \(x\in S_{opt}\)\(S_{opt}\) 是提前給出的)個步數,當某個人將棋子挪到 \(1\) 時這個人獲勝。
問對於每一個位置和先手,要求你判斷先手必勝,後手必勝還是死迴圈。
\(n\le 7000\)

CF786A題解

首先我們知道,博弈論有一個性質,就是對於一種狀態 \(sta\),如果它所有能到達的狀態都是必勝,那麼這個狀態必敗,否則必勝。
首先我們知道 \(1\) 位置必敗,於是就可以嘗試倒著推情況。
記搜即可。

CF786A代碼

#include<bits/stdc++.h>
using namespace std;
inline int read(){
    int x = 0, f = 1;char ch = getchar();
    while(ch < '0' || ch > '9'){if(ch == '-') f = -1;ch = getchar();}
    while(ch >= '0' && ch <= '9'){x = (x << 1) + (x << 3) + (ch ^ 48);ch = getchar();}
    return x * f;
}
const int maxn = 7100;
bool ans[maxn][2], vis[maxn][2];
int cnt[maxn][2];
int n;
vector<int> s[2];
void dfs(int u,int opt){
    // printf("%d %d\n",u,opt);
    if(vis[u][opt])return; vis[u][opt] = 1;
    for(int i : s[opt ^ 1]){
        int to = (u - i + n - 1) % n + 1;
        // printf("%d %d %d\n",u,to,i);
        if(to != 1){
            if(!ans[u][opt]){
                ans[to][opt ^ 1] = 1;
                dfs(to,opt ^ 1);
            }
            else if((++cnt[to][opt ^ 1]) == s[opt ^ 1].size()){
                ans[to][opt ^ 1] = 0;
                dfs(to,opt ^ 1);
            }
        }
    }
}
signed main(){
    n = read();
    for(int j = 0;j <= 1;j++)for(int i = read();i;i--)s[j].push_back(read());
    dfs(1, 0);dfs(1, 1);
    for(int i = 0;i <= 1;i++){
        for(int j = 2;j <= n;j++){
            printf(vis[j][i] ? (ans[j][i] ? "Win" : "Lose") : "Loop");
            putchar(' ');
        }
        puts("");
    }
    return 0;
}

CF786B

CF786B

CF786B題意

\(n\) 個點,現在有三種連邊(開傳送門)方式:

  • \(1\space u\space v\space w\):將 \(u\to v\),這條邊邊權是 \(w\)
  • \(2\space u\space l\space r\space w\):對 \(i\in[l,r]\),將 \(u\to i\),邊權是 \(w\)
  • \(3\space u\space l\space r\space w\):對 \(i\in[l,r]\),將 \(i\to u\),邊權是 \(w\)

求從 \(S\) 出發的單源最短路。

CF786B題解

線段樹優化建邊。
建兩棵樹,一棵自上而下的連邊,一棵自下而上建邊(分別設為 \(0,1\))。
然後對於 \(1,2\)\(1\space u\space v\space w\) 可以看做 \(2\space u\space v\space v\space w\)),將 \(1\) 樹的 \([u,u]\) 連向 \(0\) 樹的 \([l,r]\) 節點。
而對於 \(3\),將 \(0\) 樹的 \([l,r]\) 連向 \(1\) 樹的 \([u,u]\)
發現這樣連邊數量不會超過 \(\log n\) 條。
然後跑Dijsktra就好了。
註意空間開大點。

CF786B代碼

#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int read(){
    int x = 0, f = 1;char ch = getchar();
    while(ch < '0' || ch > '9'){if(ch == '-') f = -1;ch = getchar();}
    while(ch >= '0' && ch <= '9'){x = (x << 1) + (x << 3) + (ch ^ 48);ch = getchar();}
    return x * f;
}
const int maxn = 1e5 + 10;
const ll INF = 0x3f3f3f3f3f3f3f3f;
int n, m, S;

int head[maxn << 2], tot;
struct edge{
    int to, nexte;ll wei;
    edge(int to = 0,int ne = 0,ll we = 0):to(to),nexte(ne),wei(we){}
}e[maxn << 5];
void add(int u,int v,ll w){e[++tot] = edge(v,head[u],w);head[u] = tot;}

int id[maxn << 2][2],cntpoint;
int rev[maxn];
struct Segment_Tree{
    void build(int l,int r,int p,bool opt){
        id[p][opt] = ++cntpoint; if(l == r){rev[l] = p;return;}
        int mid = l + r >> 1;
        build(l,mid,p << 1,opt);build(mid + 1,r,p << 1 | 1,opt);
        if(opt == 0){add(id[p][opt],id[p << 1][opt],0);add(id[p][opt],id[p << 1 | 1][opt], 0);}
        else{add(id[p << 1][opt],id[p][opt],0);add(id[p << 1 | 1][opt],id[p][opt],0);}
    }
    void query(int l,int r,int s,int t,int p,int u,ll wei,bool opt){
        if(s <= l && r <= t){
            if(opt == 0)add(id[rev[u]][opt ^ 1],id[p][opt],wei);
            else add(id[p][opt],id[rev[u]][opt ^ 1],wei);
            return;
        }
        int mid = l + r >> 1;
        if(s <= mid)query(l,mid,s,t,p << 1,u,wei,opt);
        if(mid < t)query(mid + 1,r,s,t,p << 1 | 1,u,wei,opt);
    }
    void query(int l,int r,int u,ll wei,bool opt){query(1,n,l,r,1,u,wei,opt);}
    void DEBUG(bool opt = 0,int l = 1,int r = n,int p = 1){
        printf("l = %d r = %d p = %d,opt = %d,id = %d\n",l,r,p,opt,id[p][opt]);
        if(l == r)return;
        int mid = l + r >> 1;
        DEBUG(opt,l,mid,p << 1);DEBUG(opt,mid  + 1,r,p << 1 | 1);
    }
}tree[2];

typedef pair<ll,int> pii;
priority_queue<pii,vector<pii>,greater<pii> > que;
ll dis[maxn << 2];bool book[maxn << 2];

signed main(){
    n = read(); m = read(); S = read();int opt, l, r, u, w;
    tree[0].build(1,n,1,0); tree[1].build(1,n,1,1);
    // tree[0].DEBUG(0);tree[1].DEBUG(1);
    for(int i = 1;i <= n;i++){
        add(id[rev[i]][0],id[rev[i]][1],0);
        add(id[rev[i]][1],id[rev[i]][0],0);
    }
    for(int i = 1;i <= m;i++){
        opt = read();
        if(opt == 1){
            l = read(); r = read(); w = read();
            tree[0].query(r,r,l,w,0);
        }
        else{
            u =  read(); l = read(); r = read();w = read();
            tree[opt - 2].query(l, r, u, w, opt - 2);
        }
    }
    // for(int u = 1;u <= cntpoint;u++){
    //     for(int i = head[u];i;i = e[i].nexte){
    //         printf("%d -> %d, w = %lld\n",u,e[i].to,e[i].wei);
    //     }
    // }
    memset(dis,0x3f,sizeof(dis));
    dis[id[rev[S]][0]] = 0;que.push(make_pair(0,id[rev[S]][0]));
    while(!que.empty()){
        int u = que.top().second;que.pop();
        if(book[u])continue;book[u] = 1;
        for(int i = head[u];i;i = e[i].nexte){
            int v = e[i].to, w = e[i].wei;
            if(dis[v] > dis[u] + w){
                dis[v] = dis[u] + w;
                que.push(make_pair(dis[v],v));
            }
        }
    }
    for(int i = 1;i <= n;i++){
        if(dis[id[rev[i]][0]] == INF)dis[id[rev[i]][0]] = -1;
        printf("%lld ",dis[id[rev[i]][0]]);
    }
    return 0;
}

CF786C

CF786C

CF786C題意

給出一個長度為 \(n\) 的數列 \(a\),要你對每個 \(k\in[1,n]\),給出最小的 \(m\),使得存在一種方案,將數列 \(a\) 劃分成 \(m\) 段,使得所有段不同的數字不超過 \(k\)
\(n\le10^5\)

CF786C題解

這裡給出一個非常暴力的做法。
首先我們可以 \(O(n)\) 的計算出對於一個數字 \(k\) 的答案 \(f(k)\)
觀察這個 \(f(k)\),不難發現這個函數滿足性質:

  • \(f(k)\) 單調不增,且有連續的段。(顯然)
  • \(f(k)\) 的取值不超過 \(\sqrt{n}\) 個。(不妨取一種極端情況,即 \(a\)\(n\) 的一個排列,手玩一下就會發現這個極端情況也只有最多 \(\sqrt{n}\) 個取值)

於是就可以快樂的根號分治:

  • \(1\le k\le\sqrt{n}\) 時,直接算即可。
  • \(\sqrt{n}<k\) 時,二分找到與這個答案相等的最右端,然後這一段的答案都是這個。

如果害怕一個 \(k\) 的答案被重覆計算,那就類似記搜記錄下答案。
最大的點跑了 \(1044ms\),時限 \(2s\) 完全不慌。
時間複雜度也許是 \(O(n\sqrt{n}\log n)\) 的?但是完全跑不滿。

CF786C代碼

#include<bits/stdc++.h>
using namespace std;
inline int read(){
    int x = 0, f = 1;char ch = getchar();
    while(ch < '0' || ch > '9'){if(ch == '-') f = -1;ch = getchar();}
    while(ch >= '0' && ch <= '9'){x = (x << 1) + (x << 3) + (ch ^ 48);ch = getchar();}
    return x * f;
}
const int maxn = 1e5 + 10;
int a[maxn], n;

int book[maxn];
int ans[maxn];
int solve(int k){
    if(ans[k])return ans[k];
    memset(book,0,sizeof(book));
    int l = 0, cnt = 0, m = 0;
    for(int i = 1;i <= n;i++){
        cnt += !book[a[i]]++;
        if(cnt > k){
            for(int j = l + 1;j < i;j++)book[a[j]]--;
            m++; cnt = 1; l = i - 1;
        }
    }
    return ans[k] = m + (cnt ? 1 : 0);
}
signed main(){
    n = read();for(int i = 1;i <= n;i++)a[i] = read();
    for(int k = 1, len = sqrt(n);k <= n;k++){
        if(k <= len){printf("%d ",solve(k));}
        else{
            int res = solve(k);
            int l = k, r = n;
            while(l <= r){
                int mid = l + r >> 1;
                if(solve(mid) == res){l = mid + 1;}
                else r = mid - 1;
            }
            l--;
            for(int j = k;j <= l;j++)printf("%d ",res);
            k = l;
        }
    }
    puts("");
    return 0;
}

CF786D

*3400不會

CF786E

CF786E
我真是受不了了一道題寫兩個半小時一坤時

CF786E題意

給你一棵有 \(n\) 個節點的樹和 \(m\) 個居民,每條邊上有一個守衛 \(i\) 守衛連接 \(u_i-v_i\) 的這條邊,每個居民 \(j\) 會從節點 \(u_j\) 走到節點 \(v_j\)
現在對每個居民做出要求,要不然這個居民經過的所有守衛都有一條狗,要不然給這個居民發一條狗。
問滿足所有要求需要發多少條狗給居民,多少條狗給守衛?要求給出構造。
\(n\le2\times10^4,m\le10^4\)

CF786E題解

究極毒瘤碼農題,5.63KB極致壓行代碼你值得擁有
老規矩,先想想在序列上怎麼做?
不難想到網路流。
設源點 \(S\) 和匯點 \(T\),設網路流中一條邊形如 \((u,v,cap)\) 表示有一條 \(u\to v\),容量為 \(cap\) 的邊。
對於每個居民 \(i\) 和他的要求 \(u_i,v_i\),連接 \(w\in [u_i,v_i],(u,w,INF)\)
然後對於每個居民 \(i\),連接 \((S,i,1)\)
對於每個守衛 \(i\),連接 \((i,T,1)\)
然後跑最小割即可。
等等等等,你這麼連邊不就 \(O(n^2)\) 了嗎,這不T飛了?
好好好,那就線段樹優化建邊(為啥這套題這麼喜歡線段樹優化建邊啊
那樹上的怎麼辦?樹鏈剖分就完了。
那怎麼構造答案吶?
從源點 \(S\) 出發,每次走沒滿流的邊,走到一個守衛點時就說明至少存在一個居民在沒給狗狗的情況下包含了這個守衛,所以讓這個守衛拿一隻狗狗。
然後回頭看沒走到的居民點,說明這個居民被選擇了拿一隻狗狗,給一隻即可。
然後就沒了,只不過慢慢碼吧,我不會告訴你我碼了兩個半小時的

CF786E代碼

#include<bits/stdc++.h>
using namespace std;
inline int read(){
    int x = 0, f = 1;char ch = getchar();
    while(ch < '0' || ch > '9'){if(ch == '-') f = -1;ch = getchar();}
    while(ch >= '0' && ch <= '9'){x = (x << 1) + (x << 3) + (ch ^ 48);ch = getchar();}
    return x * f;
}
const int maxn = 2e5 + 10, INF = 0x3f3f3f3f;

int n, m;
vector<pair<int,int> > edg[maxn];

struct edge{
    int to, nexte, cap, flow;
    edge(int to = 0,int ne = 0,int ca = 0,int fl = 0):to(to),nexte(ne),cap(ca),flow(fl){}
}e[maxn << 3];
int head[maxn], tot = 1,S , T;
void add(int u,int v,int cap){e[++tot] = edge(v,head[u],cap);head[u] = tot;}
void addd(int u,int v,int cap){add(u, v, cap);add(v, u, 0);}

int fa[maxn], siz[maxn], son[maxn],dep[maxn];
int edgid[maxn];//對每條邊,存儲在dep大的點上
void dfs1(int u,int f){
    fa[u] = f;dep[u] = dep[f] + 1;
    siz[u] = 1;son[u] = 0;
    for(auto i : edg[u]){
        int v = i.first;
        if(v != f){
            dfs1(v, u); siz[u] += siz[v];
            edgid[v] = i.second;
            son[u] = siz[son[u]] > siz[v] ? son[u] : v;
        }
    }
}
int top[maxn], dfn[maxn], idx, rev[maxn];//top重鏈頂端,dfn編號,rev[dfn[u]] = u
void dfs2(int u,int t){
    top[u] = t;dfn[u] = ++idx;rev[idx] = u;
    if(!son[u])return; dfs2(son[u],t);
    for(auto i : edg[u]){
        int v = i.first;
        if(v != son[u] && v != fa[u])
            dfs2(v, v);
    }
}

int id[maxn], cntpoint;
int rrev[maxn];//rrev[l]=p表示[l,r]線上段樹上編號
struct Segment_Tree{
    int d[maxn];
    void build(int l,int r,int p){
        id[p] = ++cntpoint;
        if(l == r){addd(id[p],T,1);rrev[l] = p;return;}
        int mid = l + r >> 1;
        build(l,mid,p << 1);build(mid + 1,r,p << 1 | 1);
        addd(id[p],id[p << 1],INF);addd(id[p],id[p << 1 | 1],INF);
    }
    void query(int l,int r,int s,int t,int p,int u){//opt=0 == u->[s,t],cap=INF;opt=1 == [s,t]->T,cap=t-s
        if(s <= l && r <= t){addd(u,id[p],INF);return;}
        int mid = l + r >> 1;
        if(s <= mid)query(l,mid,s,t,p << 1,u);
        if(mid < t)query(mid + 1,r,s,t,p << 1 | 1,u);
    }
    void query(int s,int t,int u){query(1,n,s,t,1,u);}
    void build1(int l = 1,int r = n,int p = 1){
        if(l == r){
            for(int i = head[id[p]];i;i = e[i].nexte)
                if(e[i].to == T){d[p] = e[i].flow;break;}
            return;
        }
        int mid = l + r >> 1;
        build1(l,mid,p << 1);build1(mid + 1,r,p << 1 | 1);
        d[p] = d[p << 1] + d[p << 1 | 1];
    }
    void DEBUG(int l = 1,int r = n,int p = 1){
        printf("[%d,%d], p = %d, id = %d\n",l,r,p,id[p]);
        if(l == r)return; int mid = l + r >> 1;
        DEBUG(l,mid,p << 1);DEBUG(mid + 1,r,p << 1 | 1);
    }
}tree;
void query(int u,int v,int to){
    while(top[u] != top[v]){
        if(dep[top[u]] < dep[top[v]])swap(u, v);
        tree.query(dfn[top[u]],dfn[u],to);
        u = fa[top[u]];
    }
    if(dep[u] > dep[v])swap(u, v);
    if(u == v)return;
    tree.query(dfn[son[u]],dfn[v],to);
}

int dis[maxn],cur[maxn];bool book[maxn];
queue<int> que;
bool bfs(int S,int T){
    while(!que.empty())que.pop();
    for(int i = 0;i <= cntpoint;i++){dis[i] = INF;cur[i] = book[i] = 0;}
    dis[S] = 0;que.push(S);cur[S] = head[S];book[S] = 1;
    while(!que.empty()){
        int u = que.front();que.pop();book[u] = 0;
        for(int i = head[u];i;i = e[i].nexte){
            int v = e[i].to;
            if(dis[v] == INF && e[i].cap > e[i].flow){
                cur[v] = head[v];dis[v] = dis[u] + 1;
                if(!book[v]){que.push(v);book[v] = 1;}
            }
        }
    }
    return dis[T] != INF;
}
int dfs(int u,int flow,int T){
    if(!flow || u == T)return flow;
    int res = 0;
    for(int i = cur[u];i;i = e[i].nexte){
        int v = e[i].to;cur[u] = i;
        if(dis[v] == dis[u] + 1 && e[i].cap > e[i].flow){
            int tmp = dfs(v, min(flow,e[i].cap - e[i].flow),T);
            if(!tmp)dis[v] = INF;
            e[i].flow += tmp;e[i ^ 1].flow -= tmp;
            res += tmp;flow -= tmp;
        }
    }
    return res;
}
int Dinic(int S,int T){
    int mxflow = 0;
    while(bfs(S,T))mxflow += dfs(S,INF,T);
    return mxflow;
}

vector<int> citizen, guard;
bool vis[maxn];
void dfs3(int u,int f){
    if(vis[u])return;vis[u] = 1;
    for(int i = head[u];i;i = e[i].nexte){
        int v = e[i].to;
        if(e[i].cap > e[i].flow)
            dfs3(v, u);
    }
}

signed main(){
    n = read(); m = read();int u, v;cntpoint = m;
    for(int i = 1;i < n;i++){
        u = read(); v = read();
        edg[u].push_back(make_pair(v, i));
        edg[v].push_back(make_pair(u, i));
    }
    S = ++cntpoint;T = ++cntpoint;
    dfs1(1, 0);dfs2(1, 1);tree.build(1,n,1);
    
    for(int i = 1;i <= m;i++){
        u = read(); v = read();
        addd(S, i, 1); query(u, v, i);
    }
    
    int ans = Dinic(S,T);dfs3(S,S);
    for(int i = 1;i <= m;i++)
        if(!vis[i])citizen.push_back(i);
    for(int i = 2;i <= n;i++)
        if(vis[id[rrev[dfn[i]]]])guard.push_back(i);

    printf("%d\n",citizen.size() + guard.size());
    printf("%d",citizen.size());for(int i : citizen)printf(" %d",i);puts("");
    printf("%d",guard.size());for(int i : guard)printf(" %d",edgid[i]);puts("");

    // tree.DEBUG(); printf("ans = %d\n",ans);
    // for(int u = 1;u <= cntpoint;u++)
    //     for(int i = head[u];i;i = e[i].nexte)
    //         printf("%d -> %d, cap = %d, flow = %d\n",u,e[i].to,e[i].cap,e[i].flow);
    // for(int i = 1;i <= n;i++)
    //     printf("i=%d,fa=%d,siz=%d,son=%d,dep=%d,top=%d,dfn=%d,edgid=%d\n",i,fa[i],siz[i],son[i],dep[i],top[i],dfn[i],edgid[i]);
    return 0;
}

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • TS中的函數需要聲明參數列表和返回值的類型,除此只要,還有關於泛型、可選參數、不定長參數列表、回調函數、this、重載的聲明規則。 ...
  • typora-copy-images-to: media 一、數學處理 1、Math常用API 圓周率 Math.PI // 3.1415926535 生成隨機數 Math.random() 生成的是0~1之間的隨機小數,通常在實際項目中需要獲取到一個範圍內的隨機整數,利用這個隨機小數封裝一個獲取範 ...
  • 公眾號「架構成長指南」,專註於生產實踐、雲原生、分散式系統、大數據技術分享。 概述 隨著科技的進步,軟體系統的部署架構也在不斷演進,從以前傳統的物理機到虛擬機、Docker和Kubernetes,我們經歷了一系列變化。 這些技術的引入給我們帶來了更高的資源利用率、更快的部署速度和更強大的擴展性,下麵 ...
  • C++ 中要在一個函數內返回不同類型的值,你可以使用 C++17 引入的 std::variant 或 std::any,或者使用模板和多態。下麵將分別介紹這些方法。 方法一:使用 std::variant std::variant 允許你在一個函數內返回不同類型的值,但它要求所有可能的返回類型都在 ...
  • 主要探討了SpringMVC中的流程跳轉和不同形式的控制器之間的跳轉方式。首先回顧了JavaWeb中流程跳轉的核心代碼和頁面跳轉方式,並展示了在Web.xml中添加Servlet以及執行這些方式的示例。隨後,介紹了Spring MVC中的四種跳轉形式,包括控制器到JSP頁面的forward和redi... ...
  • 寫在前面 先吐槽兩句,搞個mysql安裝配置弄了4個小時,怎麼都是外網無法訪問,我靠,我特麽也是服了。 當然,後來我投降了,明天再說,學什麼不是學,娘的,換個方向,狀態依然在! Sijax是什麼? 代表 Simple Ajax ,它是一個 Python / jQuery 庫,使用 jQuery.aj ...
  • Sun公司提供了JavaMail用來實現郵件發送,但是配置煩瑣,Spring中提供了JavaMailSender用來簡化郵件配置,Spring Boot則提供了MailSenderAutoConfiguration對郵件的發送做了進一步簡化。 v準備工作 開通POP3/SMTP服務或者IMAP/SM ...
  • C語言分支結構詳解 1. if 語句 在本篇博客文章中,我們將深入探討C語言中的if語句及其相關用法。if語句是一種用於條件判斷的分支語句,它允許我們根據條件的真假來執行不同的代碼塊。 1.1 if 語句的基本語法和用法 if語句的基本語法如下所示: if (條件) { // 條件為真時執行的代碼塊 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...