最後更新日期 2024 / 01 / 01
https://cses.fi/problemset/task/1082/
定義
給予一個
以
先看一下這張圖列出了
可以發現每兩個數字就會出現一次
每三次數字就會出現一次
觀察後可知
對於一個數字
因為每
用這個做法枚舉每個數字計算就可以得到一個
但這樣還不夠快到足以處理這題
如果我們把剛剛那張圖的呈現方式改一下
上面那一橫排代表因數
下面那一行排代表該因數出現的次數
可以發現這張圖內有幾串連續的因數出現次數相同
因為事實上在計算這個的過程中只會出現最多
上面那張圖每個紅色圈起來代表一塊
如果我們可以塊為單位來計算就可以把時間複雜度降到
想像一下
如果
令
那如果不是剛好整除的呢?
再試試看
觀察後發現
這裡的
於是這樣我們就可以找到最後一個連續出現次數相同的因數
最後只要把每次一塊的第一個數和最後一個數用梯形公式求總和乘上共同的出現次數就可以得到答案了
不過這邊要注意的是
因為答案很大所以題目要我們對
但梯形公式中又會用到除法
所以我們不能直接除
需要先求出模反元素再乘進去才行
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod = 1e9 + 7;
const int inv = 500000004;
signed main() {
int n;
cin >> n;
int cur = 1;
int ans = 0;
while (cur <= n) {
int cnt = n / cur;
int last = n / cnt;
int sum = ((((last + cur) % mod) * ((last - cur + 1) % mod) % mod) * inv) % mod;
ans += ((sum % mod) * (cnt % mod)) % mod;
cur = last + 1;
}
cout << ans % mod << endl;
}
找到兩個數字 使得兩數的最大公因數盡量大可以把題目想成 找到最大的 x 使得陣列中出現至少兩個他的倍數 於是我們可以先用 cnt 陣列紀錄每個數字的出現次數 然後枚舉每個可能的因數 假設目前枚舉到 k 從 k、2k、3k dots 計算陣列中存在多少個倍數 根據調和級數.harmonic-series可以算出時間複雜度為 On log ncppconst int maxn = 1e6 + 10;int cntmaxn;signed main { int n; cin n; vectorint vn; for int i = 0; i n; i++ { cin vi; cntvi++; } for int k = maxn; k 0; k-- { int cur = 0; for int j = k; j maxn; j += k { cur += cntj; } if cur = 2 { cout k endl; return 0; } }}
CSES你有一個由 A、C、G、T 組成的字串 目標是算出同樣的字母最多連續重複幾次把整個字串從左邊往右掃 用一個 curLen 變數維護目前的長度 遇到一個字母時 curLen 加 1 如果跟上個字母不同就把 curLen 歸零 每次掃過一個字母再用 maxLen 維護出現過最大的 curLencppusing namespace std;signed main { char chr, tmp = 'X'; int maxLen = 1, curLen = 1; while cin chr { if tmp = 'X' tmp == chr { curLen++; } else { curLen = 1; } maxLen = maxmaxLen, curLen; tmp = chr; } cout maxLen endl;}
CSES給你 n 位客人的進入和離開餐廳的時間 輸出最多同時有幾位客人同時在餐廳- n le 2 times 10^5把每個人加入時間和離開的時間分別看成兩個時間點 並把所有時間點加入陣列後一起排序 然後用一個變數來維護目前餐廳人數 每次遇到加入就增加 反之遇到離開就減少 維護中遇到的最大值就是答案了 時間複雜度:Oncpp using namespace std; signed main { int n; cin n; vectorpii v; for int i = 0; i n; i++ { int s, t; cin s t; v.pushback{s, true}; v.pushback{t, false}; } sortv.begin, v.end; int cur = 0; int ans = 0; for auto e : v { if e.ss == true cur++; else cur--; ans = maxcur, ans; } cout ans endl;}
CSES