forked from wisdompeak/LeetCode
-
Notifications
You must be signed in to change notification settings - Fork 1
[pull] master from wisdompeak:master #359
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
91 changes: 91 additions & 0 deletions
Segment_Tree/3671.Sum-of-Beautiful-Subsequences/3671.Sum-of-Beautiful-Subsequences.cpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
class BIT{ | ||
public: | ||
int N; | ||
vector<long long>bitArr; // Note: all arrays are 1-index | ||
vector<long long>nums; | ||
long long M = 1e9+7; | ||
|
||
void init(int N) | ||
{ | ||
this->N = N; | ||
bitArr.resize(N+1); | ||
nums.resize(N+1); | ||
} | ||
|
||
// increase nums[i] by delta | ||
void updateDelta(int i, long long delta) { | ||
int idx = i; | ||
while (idx <= N) | ||
{ | ||
bitArr[idx]+=delta; | ||
bitArr[idx] %= M; | ||
idx+=idx&(-idx); | ||
} | ||
} | ||
|
||
// sum of a range nums[1:j] inclusively | ||
long long queryPreSum(int idx){ | ||
long long result = 0; | ||
while (idx){ | ||
result += bitArr[idx]; | ||
// result %= M; | ||
idx-=idx&(-idx); | ||
} | ||
return result; | ||
} | ||
|
||
// sum of a range nums[i:j] inclusively | ||
long long sumRange(int i, int j) { | ||
return queryPreSum(j)-queryPreSum(i-1); | ||
} | ||
}; | ||
|
||
long long MOD = 1e9+7; | ||
|
||
class Solution { | ||
public: | ||
int totalBeauty(vector<int>& nums) { | ||
int mx = *max_element(begin(nums), end(nums)); | ||
vector<vector<int>>pos(mx+1); | ||
for (int i=0; i<nums.size(); i++) { | ||
for (int j=1; j*j<=nums[i]; j++) { | ||
if (nums[i]%j==0) { | ||
pos[j].push_back(i); | ||
if (j*j!=nums[i]) pos[nums[i]/j].push_back(i); | ||
} | ||
} | ||
} | ||
|
||
vector<long long>seq(mx+1); | ||
for (int g=1; g<=mx; g++) { | ||
map<int,int>mp; | ||
for (int x: pos[g]) mp[nums[x]] = 1; | ||
int idx = 0; | ||
for (auto& [k,v]:mp) v = ++idx; | ||
|
||
vector<int>arr; | ||
for (int x: pos[g]) arr.push_back(mp[nums[x]]); | ||
|
||
BIT bit; | ||
bit.init(arr.size()); | ||
for (int x: arr) { | ||
long long ans = bit.queryPreSum(x-1) + 1; | ||
seq[g] = (seq[g]+ans)%MOD; | ||
bit.updateDelta(x, ans); | ||
} | ||
} | ||
|
||
vector<long long>ret(mx+1); | ||
for (int g=mx; g>=1; g--) { | ||
ret[g] = seq[g]; | ||
for (int j=g*2; j<=mx; j+=g) | ||
ret[g] = (ret[g]-ret[j]+MOD) % MOD; | ||
} | ||
|
||
long long ans = 0; | ||
for (int g=mx; g>=1; g--) { | ||
ans = (ans + g*ret[g]) % MOD; | ||
} | ||
return ans; | ||
} | ||
}; |
12 changes: 12 additions & 0 deletions
Segment_Tree/3671.Sum-of-Beautiful-Subsequences/Readme.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
### 3671.Sum-of-Beautiful-Subsequences | ||
|
||
此题包含了两个知识点。我们拆开来分析。 | ||
|
||
第一个问题,对于任意的正整数g,如何计算在数组里有多少个strictly increasing subsequence并且序列中每个元素都是"g的倍数"。假设我们已经通过预处理,知道数组里g的倍数位于[i1,i2,...,ik]的位置上。注意我们只需要构造严格递增的序列,所以我们需要只知道它们之间的大小关系和位置关系,但是不需要知道绝对大小和绝对位置,故我们可以离散化,转化为类似[1,3,5,2,4]这样的形式,表示数组里有5个数是g的倍数,且它们的相对位置和相对大小都可以用这样的形式表示出来。于是我们就构造出了这样一个问题:里面有多少个严格递增的序列? | ||
|
||
这是一个经典问题,我们可以用树状数组来解。我们想象一个长度为5的空数组,需要依照上述次序涂黑。首先我们在填写1时,以它结尾的递增序列只有一个,记作f(1)。然后我们填写3时,以它结尾的递增序列就是`f(3)=f(1)+1`,表示以1结尾的递增序列再附加上3,或者单独的3也可以构成一个符合条件的序列。然后我们填写5时,以它为结尾的递增序列就是`f(5)=f(1)+f(3)+1`。然后我们填写2时,以它结尾的递增序列就是`f(2)=f(1)+1`...由此我们可以看出f(x)就是BIT数组前缀和`f(1)+f(2)+...+f(x-1)`再加1.于是我们就可以求出所有的f(x)并且求和,就得出:数组里有多少个严格递增序列、并且每个元素都是"g的倍数",我们记作p(g). | ||
|
||
在有了p(g)的基础上,我们如何进一步求出数组里有多少个严格递增序列、并且所有元素的GCD恰好是g呢?我们记作这样的解是ret(g),其实就是删去在p(g)里去除"2以上g的倍数"的情况,即`ret(g) = p(g)-ret(2g)-ret(3g)-...-ret(kg)`. 所以我们只需要对g按从大到小的顺序求解q:当解到ret(g)时,p(g)和`ret(2g)...ret(kg)`就都是已知的了。初始条件是对于数组里的最大元素mx,`ret(mx) = 1`. | ||
|
||
最终返回`g*ret(g)`对于g=1,2,..,mx的之和 | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.