日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

厦门大学“网宿杯“17届程序设计竞赛决赛(同步赛) #题解 #题目都超有趣呀

發(fā)布時(shí)間:2023/12/20 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 厦门大学“网宿杯“17届程序设计竞赛决赛(同步赛) #题解 #题目都超有趣呀 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

  • A.這波啊,這波是.....
  • B.李在贛神魔
  • C.電競希金斯
  • D.財(cái)富密碼
  • E.蕪湖起飛
  • F.這題多撈啊
  • G.正方形打野
  • H.時(shí)間管理

A.這波啊,這波是…

鏈接:https://ac.nowcoder.com/acm/contest/5945/A
來源:??途W(wǎng)

題目描述
“這波啊,這波是肉蛋蔥雞!”
打出口令即可領(lǐng)取簽到獎(jiǎng)勵(lì)。

輸入描述:
沒有輸入。

輸出描述:
見樣例輸出。

示例1

輸入
non

輸出
roudancongji

說明
如果你不知道題目在講什么也沒關(guān)系,你只需要輸出樣例即可通過本題。

思路:
簽到題,看懂提就行

代碼:

#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 1010; int a[maxn]; int main() {cout << "roudancongji" << endl;return 0; }

B.李在贛神魔

鏈接:https://ac.nowcoder.com/acm/contest/5945/B
來源:牛客網(wǎng)

題目描述
我們要做一個(gè)旋轉(zhuǎn)木馬! 輸入一個(gè)n\times nn×n的字符矩陣,將其順時(shí)針旋轉(zhuǎn)90度后輸出。
輸入描述:
每個(gè)測試點(diǎn)僅包含一組輸入數(shù)據(jù)。
第一行一個(gè)整數(shù)n(1 \leq n \leq 1000)n(1≤n≤1000),表示矩陣大小。
接下來n行,每行一個(gè)長度為n的字符串,僅包含小寫字母,表示這個(gè)矩陣。
輸出描述:
輸出順時(shí)針旋轉(zhuǎn)90度后的矩陣,行末不要出現(xiàn)多余空格。

示例1
輸入
3
aaa
bbb
ccc

輸出
cba
cba
cba
思路:
也是個(gè)簽到題,不需要任何算法知識背景,不多說了

代碼:

#include <stdio.h> main() {int n,i,j;char a[1005][1005],b[1005][1005];scanf("%d",&n);for(i=0;i<n;i++){scanf("%s",a[i]);}for(i=0;i<n;i++){for(j=0;j<n;j++){b[j][n-i-1]=a[i][j];}}for(i=0;i<n;i++){printf("%s\n",b[i]);} }

C.電競希金斯

鏈接:https://ac.nowcoder.com/acm/contest/5945/C
來源:??途W(wǎng)

題目描述
大司馬綽號“電競希金斯”,所以他的幾何非常好。他發(fā)明的“馬氏幾何”多次挑戰(zhàn)牛頓和愛因斯坦的理論,連奧沙利文都直呼內(nèi)行。
本題就是一道關(guān)于計(jì)算幾何的題目。
給定一條直線ax+by+c=0,請以編號從小到大的順序輸出這條直線經(jīng)過的象限。
注意,x軸和y軸不屬于任何一個(gè)象限,第一象限為x,y>0的區(qū)域,第二象限為x<0,y>0的區(qū)域,第三象限為x,y<0的區(qū)域,第四象限為x>0,y<0的區(qū)域。
輸入描述:
每個(gè)測試點(diǎn)僅包含一組輸入數(shù)據(jù)。
僅一行空格隔開的三個(gè)整數(shù)a,b,c(-100 \leq a,b,c \leq 100)a,b,c(?100≤a,b,c≤100)
其中a和b不會(huì)同時(shí)等于0
輸出描述:
一行,按照順序輸出經(jīng)過的象限。
如果直線不經(jīng)過任何象限,請輸出"non"。

示例1
輸入
1 2 3

輸出
2 3 4

思路:
簡單的數(shù)學(xué)題,沒啥好說的…

代碼:

#include <bits/stdc++.h> using namespace std; int main() {int a, b, c;cin >> a >> b >> c;if (a == 0) {if (c == 0)cout << "non" << endl;else {if (b * c > 0)cout << "3 4" << endl;else cout << "1 2" << endl;}}else if (b == 0) {if (c == 0)cout << "non" << endl;else {if (a * c > 0)cout << "2 3" << endl;else cout << "1 4" << endl;}}else {if (c == 0)if (a * b > 0)cout << "2 4" << endl;else cout << "1 3" << endl;else {if (a * b < 0) {if (b * c < 0)cout << "1 2 3" << endl;else cout << "1 3 4" << endl;}else {if (b * c < 0)cout << "1 2 4" << endl;else cout << "2 3 4" << endl;}}}return 0; }

D.財(cái)富密碼

鏈接:https://ac.nowcoder.com/acm/contest/5945/D
來源:??途W(wǎng)

題目描述
“我們廈大的ACM實(shí)在是太厲害了”
在我校無數(shù)的菜雞中,這句話打開了財(cái)富之門,因此被稱為財(cái)富密碼。
事實(shí)上,關(guān)于密碼學(xué)的研究里面有很多涉及到數(shù)論的知識,以下就是一道例題。
求有多少整數(shù)n(1 \leq n \leq x)n(1≤n≤x)滿足na^{n} \equiv b (mod \ p)na
n≡b(mod p),其中p是一個(gè)質(zhì)數(shù)。
看到這里你可能認(rèn)為我會(huì)解釋上述符號的意思,然而如果你看不懂上面的式子,那么我不建議你嘗試這道題目,所以這里沒有解釋。

輸入描述:
每個(gè)測試點(diǎn)僅包含一組輸入數(shù)據(jù)。
第一行,四個(gè)以空格隔開的正整數(shù),分別表示a,b,p,x(2 \leq p \leq 10^6,1 \leq x \leq 10^{12},1 \leq a,b < p)a,b,p,x(2≤p≤10 6,1≤x≤10 12,1≤a,b<p)

輸出描述:
一個(gè)正整數(shù),符合條件的n的個(gè)數(shù)。

示例1
輸入
2 3 5 8

輸出
2

思路:
需要一些簡單的數(shù)論知識:

費(fèi)馬小定理:若 p為質(zhì)數(shù),而整數(shù)a不是 p的倍數(shù),則 。

逆元:定義整數(shù) a 在模 p 意義下的逆元為 x,則 ,
可記作 。
在 1條件下,有 。
因?yàn)?。

然后到這道題:
首先由 費(fèi)馬小定理 可以得到 ,
因此可以設(shè) 。
然后推式子:



由于 ,范圍為 。故可以枚舉 t,通過上式計(jì)算 k。
需要用到快速冪,一次計(jì)算的復(fù)雜度在 log級別。整體估計(jì)復(fù)雜度是可以通過的。

在已知 t 的情況下,我們根據(jù)這個(gè)式子可以求出一個(gè) ,
顯然任意 ,
即 ,
都有: 時(shí) 。

有限制條件: 。
對于一個(gè)確定的 M>=0,我們要求的就是有多少個(gè)整數(shù) ,使得 n在范圍之內(nèi)。

然后在范圍內(nèi)的計(jì)入答案就可以了。
代碼:

#include <bits/stdc++.h> using namespace std; using ll = long long; int a, b, p; ll x; int qpow(int x, int n) {assert(n >= 0);int res = 1;while(n) {if(n & 1) res = 1ll * res * x % p;x = 1ll * x * x % p;n >>= 1;}return res; } int inv(int x) { return qpow(x, p - 2); } int main() {cin >> a >> b >> p >> x;ll ans = 0;int inv1 = inv(p - 1);for(int t = 0; t < p - 1; t++) {int k = (1ll * b * inv(qpow(a, t)) - t) * inv1 % p;k = (k + p) % p;ll d = x - 1ll * k * (p - 1) - t;if(d >= 0) ans += d / (1ll * p * (p - 1)) + 1;}cout << ans << endl; }

E.蕪湖起飛

鏈接:https://ac.nowcoder.com/acm/contest/5945/E
來源:牛客網(wǎng)

題目描述
安徽蕪湖有n個(gè)機(jī)場,一共有m條線路在空管部門報(bào)備。
每條線路單向連接兩個(gè)機(jī)場,并且需要的通行時(shí)間每天都可能不一樣。
具體來說,設(shè)目前是第x天,那么第i條線路所需要的通行時(shí)間為k_ix+b_ik
i x+b i。
一年一共有H天,也就是說,x取[0,H]中的整數(shù)。
現(xiàn)在大司馬想從1號機(jī)場在一天內(nèi)換乘任意多次航班前往n號機(jī)場,他總是選擇用時(shí)最短的方式,現(xiàn)在他想知道哪一天需要花最長的時(shí)間。
輸入描述:
每個(gè)測試點(diǎn)僅包含一組輸入數(shù)據(jù)。
第一行三個(gè)整數(shù)n,m,H(1 \leq n,m \leq 114514,1 \leq H \leq 10^9)n,m,H(1≤n,m≤114514,1≤H≤10 9),表示機(jī)場的數(shù)量,線路的數(shù)量和x的取值范圍。
接下來m行,每行四個(gè)整數(shù)u_i,v_i,k_i,b_i(1 \leq u_i,v_i \leq n,-10^9 \leq k_i,b_i \leq 10^9)u i,v i,k i ,b i(1≤u i ,v i ≤n,?10 9 ≤k i,b i≤10 9),表示一條線路從u_iu i機(jī)場單向前往v_iv i機(jī)場,并且第x天需要k_ix+b_ik ix+b i的時(shí)間來通行。
同一對機(jī)場之間可能有多條航線,一條航線的起點(diǎn)和終點(diǎn)可能相同。
保證在[0,H]中的任意一天,每條航線的長度非負(fù)且不超過10^910
9,且從1號機(jī)場可以到達(dá)n號機(jī)場。

輸出描述:
輸出一行一個(gè)整數(shù),表示最長的用時(shí)。

示例1
輸入
4 6 2
1 2 -2 6
1 3 3 3
1 4 -1 4
3 2 1 5
3 4 -3 7
2 4 0 5

輸出
4

思路:
這個(gè)題目的路徑是變化的,因?yàn)閎i和ki是確定的,所以路徑長度隨著天數(shù)的變化而變化。題目要求的是0-h天里花費(fèi)時(shí)間最長的那一天。因?yàn)槁窂阶兓]有規(guī)律。考慮到bi和ai都是固定的,最短的情況應(yīng)該就是第0天或者第h天。那么答案應(yīng)該在0-h中間,0-h的最短路可以看作是一個(gè)向上凸的二次函數(shù)曲線,可以用三分的方法求出最高點(diǎn)。三分設(shè)左邊界為l,右邊界為r,ml=(l+r)>>1,mr=(r+ml)>>1;如果ml天的最短路大于mr天的最短路,那么答案可能的區(qū)間可以縮小到[l,mr],反之區(qū)間縮小為[ml,r]。mr-ml<10后,直接暴力把答案精確的求出來就行了

代碼:

#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N = 214514; const int inf = 0x3f3f3f3f; struct line{int v;ll k, b;};vector<line> g[N]; ll dist[N]; int n, m, h, vis[N];struct node{int v;ll cost;bool operator <(const node n)const{return cost > n.cost;} }; priority_queue<node>q;ll dij(ll x){for(int i = 1; i <= n; i++){dist[i] = 1e18;vis[i] = 0;}q.push({1, 0});dist[1] = 0;while(q.size()){node cd = q.top();q.pop();if(vis[cd.v])continue;vis[cd.v] = 1;for(line it: g[cd.v]){int to = it.v;ll cost = it.k * x + it.b;if(dist[to] > dist[cd.v] + cost){dist[to] = dist[cd.v] + cost;q.push({to, dist[to]});}}}return dist[n]; }ll work(int l, int r){if(r - l <= 10){ll ans = 0;for(int i = l; i <= r; i++){ans = max(ans, dij(1ll * i));}return ans;}int midl = (l + r) / 2;int midr = (midl + r) / 2;ll maxl = dij(1ll * midl);ll maxr = dij(1ll * midr);if(maxl >= maxr){return work(l, midr);}else{return work(midl, r);}}int main(){scanf("%d %d %d", &n, &m, &h);for(int i = 1; i <= m; i++){int u, v;ll k, b;scanf("%d %d %lld %lld", &u, &v, &k, &b);g[u].push_back({v, k, b});}printf("%lld\n", work(0, h));}

F.這題多撈啊

鏈接:https://ac.nowcoder.com/acm/contest/5945/F
來源:牛客網(wǎng)

題目描述
給定一個(gè)正整數(shù)n,請求出所有滿足如下兩個(gè)條件的正整數(shù)集合x[1],x[2]…x[n]:

  • x[1]+x[2]+…+x[n]=2n
  • 不存在一個(gè)劃分將集合劃分成和相等的兩部分,也就是說,集合的任意子集和均不為n。
    請按照集合中元素升序排序后字典序從小到大的順序輸出答案,若不存在這樣的集合請不要輸出任何字符。
  • 輸入描述:
    每個(gè)測試點(diǎn)僅包含一組測試數(shù)據(jù)。
    第一行一個(gè)正整數(shù)n(1 \leq n \leq 1000)n(1≤n≤1000)。

    輸出描述:
    多行,每行代表一個(gè)可能的答案序列。
    同一個(gè)序列內(nèi)所有數(shù)從小到大排序,相鄰兩個(gè)數(shù)之間用一個(gè)空格隔開,行首尾不要添加多余空格。

    示例1
    輸入
    3

    輸出
    1 1 4

    思路:

    我們先拿一些具體的例子試一試吧,看能不能找到突破口。
    n == 1 :[2]
    n == 2 :[1,3]
    n == 3 :[1,1,4] 、[2,2,2]
    n == 4 :[1,1,1,5]
    n == 5 :[1,1,1,1,6] 、 [2,2,2,2,2]
    。。。。。。。。。
    我們似乎得到了什么規(guī)律了
    首先對任意n,[1,1,1,1,1,1,…,n+1]一定是正確的(n-1個(gè)1,1個(gè)n+1)
    而當(dāng)n為奇數(shù)時(shí)[2,2,2,2,2,2,2…]也是正確的(n個(gè)2)
    n==1時(shí)兩者重合了
    這兩點(diǎn)都不難理解,重要的是接下來的一個(gè)歸納:
    除了這兩種其他的任何集合都會(huì)有和為n的子集,不滿足情況!!!!!!!!!!!

    下面我們來證明這個(gè)歸納!!
    我們從這開始[1,1,1,1,1,1,…,n+1] 這是我們目前的序列
    我們有n-1個(gè)1,1個(gè)n+1
    我們從n+1向前扔k個(gè)1, n>=k>=1
    這k個(gè)1一共落在了b個(gè)位置上, k>=b>=1
    那么我們現(xiàn)在還擁有:
    A、n-1-b 個(gè) 1
    B、一個(gè) n+1-k
    C、b個(gè)總和為k+b,單個(gè)最小為2的數(shù)
    我們要證明這些數(shù)一定能湊成n
    首先我們有了n-1-b個(gè)1了那么這意味著什么?
    意味著如果我們用B和C中的元素湊成
    [b+1,b+2,b+3,b+4,…,n-1,n]
    中的任意一個(gè)數(shù)值游戲結(jié)束!!!!!
    而有趣的是,我們A,B,C中所有元素的數(shù)值總和為2n
    那么B和C的元素的總和為2n - (n-1-b)
    為n+1+b !!!(看上面的區(qū)間)
    正好為:(b+1) + n、(b+2) + (n-1)、(b+3) + (n-2) 、(b+4) + (n-3) 。。。。。。。
    而B和C中至少也有兩個(gè)元素,那么只要區(qū)間[b+1,b+2,b+3,b+4,。。。。n-1,n]
    保持對稱性的情況下,一定能找到n即一定不成立!!!!!!
    那么什么時(shí)候不保持對稱性呢?b+1 == n即b == n-1
    也就是說,[1,1,1,1,1,…,n+1]最后一位向前n-1位都發(fā)了一個(gè)1
    大家都變?yōu)榱薣2,2,2,2,2,2,2,2,2,2,…]
    n位奇數(shù)時(shí)true,為偶數(shù)時(shí)false
    證明完畢!!!!!!!!!!

    證明并不嚴(yán)謹(jǐn),可能會(huì)有漏洞,,,,如果發(fā)現(xiàn)希望指出,謝謝

    代碼:

    #include<bits/stdc++.h> using namespace std; int main() {int n;scanf("%d",&n);if(n==1){printf("2");return 0;}if(n&1){for(int i=1;i<=n-1;i++)printf("1 ");printf("%d\n",n+1);for(int i=1;i<=n;i++)printf("2 ");}else{for(int i=1;i<=n-1;i++)printf("1 ");printf("%d\n",n+1);}return 0; }

    G.正方形打野

    鏈接:https://ac.nowcoder.com/acm/contest/5945/G
    來源:牛客網(wǎng)

    題目描述
    大司馬的重要理論成果之一即所謂正方形打野,本題恰好與正方形相關(guān)。
    大司馬的家的地板可以看成有n \times mn×m個(gè)格子的矩形?,F(xiàn)在他需要用一些顏色的瓷磚來鋪滿這個(gè)房間,每種顏色的瓷磚擺放數(shù)量不受限制,但不能在同一個(gè)格子上覆蓋多塊瓷磚,更不能有空格子。
    所有的瓷磚都是正方形的,然而這些瓷磚的邊長卻不一定相等,如:1 \times 11×1的瓷磚可以覆蓋一個(gè)格子,2 \times 22×2的瓷磚可以覆蓋4個(gè)格子。每一種不同的瓷磚的顏色分別為大寫字母A,B,C,D,E等以此類推,本題數(shù)據(jù)保證所需顏色不會(huì)超過26種。
    大司馬是一個(gè)有強(qiáng)迫癥的人,他不能忍受地板上出現(xiàn)一個(gè)非正方形的色塊,即所有同色連通塊必須為正方形,這里的連通指上下左右四連通。
    當(dāng)大司馬的房子為4 \times 34×3時(shí)那么他的地板可以覆蓋成這樣:
    AAA
    AAA
    AAA
    BCB
    不能覆蓋成這樣:
    AAA
    AAA
    AAA
    ACB
    因?yàn)锳對應(yīng)的同色連通塊不是正方形,多了一塊角。
    大司馬希望按照從上到下,從左到右的順序他房子地板顏色的字典序最小。
    即將第一行,第二行……第n行從左到右對應(yīng)的字母序列串成一個(gè)字符串,其字典序最小。
    對于給定的n,m,請你輸出對應(yīng)的方案。
    輸入描述:
    每個(gè)測試點(diǎn)僅包含一組輸入數(shù)據(jù)。
    第一行兩個(gè)空格隔開的正整數(shù)n,m(n,m<=100)
    輸出描述:
    n行,每行一個(gè)長度為m的字符串,表示最終的擺放方案。
    示例1
    輸入
    復(fù)制
    13 15
    輸出
    復(fù)制
    AAAAAAAAAAAAABA
    AAAAAAAAAAAAACB
    AAAAAAAAAAAAABA
    AAAAAAAAAAAAACB
    AAAAAAAAAAAAABA
    AAAAAAAAAAAAACB
    AAAAAAAAAAAAABA
    AAAAAAAAAAAAACB
    AAAAAAAAAAAAABA
    AAAAAAAAAAAAACB
    AAAAAAAAAAAAABA
    AAAAAAAAAAAAACB
    AAAAAAAAAAAAABA

    思路:
    我們仔細(xì)看這道題的要求:
    1.保證所有連通塊是正方形
    2.盡量讓這個(gè)地板從上到小,從左到右最小
    那么我們想想,首相對于第一個(gè)格子我們首先肯定會(huì)鋪A之后向右看盡量鋪設(shè)A直到這一行鋪滿
    或者說是列數(shù)不足以讓我們維持正方形了。
    這里我們只要貪心的考慮讓右邊的格子盡量小就可以了,無需考慮下方。
    那關(guān)鍵是接下來倘若行數(shù)沒有鋪完列數(shù)鋪完的情況下怎么考慮?
    例:
    AAAABA
    AAAACB
    AAAABA
    AAAACB
    我們是怎樣得出右邊的
    BA
    CB
    BA
    CB
    的呢?
    我們在上面的分析中有一句話:
    這里我們只要貪心的考慮讓右邊的格子盡量小就可以了
    也就是說我們只用考慮右方。
    假設(shè)我們現(xiàn)在開始鋪設(shè)瓷磚B,我們判斷下一個(gè)即第一行最后一列該鋪設(shè)什么
    我們有兩種選擇:
    1.鋪設(shè)瓷磚B同時(shí)形成正方形(這里要保證不超過列數(shù)與行數(shù))
    2.鋪設(shè)其他瓷磚,瓷磚B的正方形到頭,新的時(shí)***啟。(這里的其他瓷磚是可鋪設(shè)的)
    那我們的問題主要是接下來鋪設(shè)的時(shí)刻如何正確選擇操作1,2
    我們會(huì)在兩種情況下使用操作2
    (1):鋪設(shè)B無法形成正方形
    (2):在可鋪設(shè)的瓷磚中有比B要小的瓷磚
    滿足這兩個(gè)條件的任意一個(gè),我們就不得不選擇操作2而非操作1
    其實(shí)上述的兩種情況我們可以歸為一種:在可鋪設(shè)的瓷磚中最小的瓷磚不是B
    那么我們就會(huì)采取操作2

    如此我們從上到下,從左到右的遍歷矩陣,正方形的填充矩陣。

    代碼:

    #include<iostream>; #include<algorithm>; #include<vector>; using namespace std; int n, m; char ans[110][110]; int dir[4][2] = { 1,0,-1,0,0,1,0,-1 };char get(int x0,int y0) {vector<char> tmp;if (ans[x0][y0])return ans[x0][y0];for (int i = 0;i < 4;i++) {int x = x0 + dir[i][0];int y = y0 + dir[i][1];if (x > n || x <= 0 || y > m || y <= 0)continue;if (ans[x][y] != 0)tmp.push_back(ans[x][y]);}for (char ch = 'A';ch <= 'Z';ch++) {bool help = true;for (char cch : tmp)if (cch == ch) {help = false;break;}if (help)return ch;} }int main() {ios::sync_with_stdio(0);cin >> n >> m;for (int i = 1;i <= n;i++) {for (int j = 1;j <= m;j++) {if (ans[i][j])continue;char mychar = get(i, j);int len = 0;while (i + len <= n && j + len <= m && get(i, j + len) == mychar)len++;for (int k = 0;k < len;k++)for (int w = 0;w < len;w++)ans[i + k][j + w] = mychar;}}for (int i = 1;i <= n;i++) {for (int j = 1;j <= m;j++)cout << ans[i][j];cout << endl;} }

    H.時(shí)間管理

    鏈接:https://ac.nowcoder.com/acm/contest/5945/H
    來源:??途W(wǎng)

    題目描述
    大司馬每天日程太多,需要一個(gè)高效的數(shù)據(jù)結(jié)構(gòu)進(jìn)行時(shí)間管理。經(jīng)過研究,他認(rèn)為這個(gè)問題可以被歸結(jié)如下:
    給定一個(gè)長度為n的序列,第i個(gè)元素為a_ia
    i
    ?
    ,請支持如下兩種操作:
    1\ l\ r\ x(1 \leq l \leq r \leq n,1 \leq x \leq 10^9)1 l r x(1≤l≤r≤n,1≤x≤10
    9
    ),表示將a_l \sim a_ra
    l
    ?
    ~a
    r
    ?
    的值都與x取最大公約數(shù),即對于l \leq i \leq rl≤i≤r,將a_ia
    i
    ?
    替換為gcd(a_i,x)gcd(a
    i
    ?
    ,x),兩個(gè)數(shù)的最大公約數(shù)是能夠同時(shí)整除兩個(gè)數(shù)的最大數(shù)。
    2\ l\ r(1 \leq l \leq r \leq n)2 l r(1≤l≤r≤n),詢問此時(shí)a_l \sim a_ra
    l
    ?
    ~a
    r
    ?
    的和。
    請注意,操作有時(shí)間順序,2類操作輸出的是進(jìn)行詢問時(shí)對應(yīng)區(qū)間的和。
    輸入描述:
    每個(gè)測試點(diǎn)僅包含一組輸入數(shù)據(jù)。
    第一行兩個(gè)整數(shù)n,m(1 \leq n,m \leq 114514)n,m(1≤n,m≤114514),表示序列長度和操作個(gè)數(shù)。
    第二行n個(gè)整數(shù),第i個(gè)整數(shù)表示a_ia
    i
    ?
    的初始值(1 \leq a_i \leq 10^9)(1≤a
    i
    ?
    ≤10
    9
    )。
    接下來m行,每行為題目描述提到的的兩種格式之一,表示一次操作,操作按照時(shí)間順序給出。
    輸出描述:
    按照輸入順序,對于每個(gè)2類操作,輸出一行一個(gè)整數(shù)表示對應(yīng)的和。

    示例1
    輸入
    6 4
    9 9 6 2 5 1
    1 1 3 6
    2 2 5
    1 2 5 4
    2 1 6

    輸出
    16
    10

    思路:
    這道題跟區(qū)間開方思路類似。
    每次對一個(gè)區(qū)間進(jìn)行g(shù)cd的話一般會(huì)有大部分會(huì)變成1,可以用一些小技巧來保證復(fù)雜度不會(huì)太差,用一個(gè)tag變量去標(biāo)記一下這個(gè)區(qū)間是不是全都相等,再用一個(gè)sam變量去標(biāo)記區(qū)間全相等的時(shí)候的元素大小,這樣修改的時(shí)候?qū)τ趨^(qū)間元素都相等的直接對sam進(jìn)行g(shù)cd即可。最后用一個(gè)線段樹維護(hù)標(biāo)記。

    代碼:

    #include<bits/stdc++.h> #define ls cur<<1 #define rs cur<<1|1 using namespace std;typedef long long ll; const int maxn=2e5+10;ll sum[maxn<<2],a[maxn<<2],ma[maxn<<2],gd[maxn<<2],tag[maxn<<2],sam[maxn<<2];void pushup( int cur ) {sum[cur]=sum[ls]+sum[rs]; tag[cur]=tag[ls] & tag[rs];if( tag[cur] ) {if( sam[ls]==sam[rs] ) sam[cur]=sam[ls]; else tag[cur]=0;} }void pushdown( int cur ,int l,int r ) {if( tag[cur] ){int mid=l+r>>1;sam[ls]=sam[rs]=sam[cur];sum[ls]=(mid-l+1)*sam[ls];sum[rs]=(r-mid)*sam[rs];}}void build( int cur,int l,int r ) {if( l==r ){sum[cur]=a[l];tag[cur]=1;sam[cur]=a[l];return;}tag[cur]=0;int mid=l+r>>1;build(ls,l,mid);build(rs,mid+1,r);pushup(cur); }void update( int cur,int l,int r,int L,int R,ll p ) {if( L<=l && r<=R ){if( tag[cur] ){sam[cur]=__gcd(sam[cur],p);sum[cur]=sam[cur]*(r-l+1);return;}}pushdown(cur,l,r);if( l==r ){sam[cur]=sum[cur]=__gcd(a[l],p);return;}int mid=l+r>>1;if( mid>=L ) update(ls,l,mid,L,R,p);if( mid<R ) update(rs,mid+1,r,L,R,p);pushup(cur); }ll get_sum( int cur,int l,int r,int L,int R ) {if( L<=l && r<=R ) return sum[cur];int mid=l+r>>1;ll ans=0;pushdown(cur,l,r);if( L<=mid ) ans+=get_sum(ls,l,mid,L,R);if( R>mid ) ans+=get_sum(rs,mid+1,r,L,R);return ans; }

    如有錯(cuò)誤,歡迎指正~

    總結(jié)

    以上是生活随笔為你收集整理的厦门大学“网宿杯“17届程序设计竞赛决赛(同步赛) #题解 #题目都超有趣呀的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。