本題的收獲是,要學會反向思維,正向找包含1的太多,我們就反向找,全排列-只有0的不滿足題意的就是答案,一共有n-m個0,m個1,插空法,一共有m+1個地方可以插入0序列,總排列數為(n+1)*n/2,每一段0序列的數是l*(l+1)/2,我們要使答案最大,就要使l盡可能小,和上題一樣的思維,要最小,就取平均數,l=floor((n-m)/(m+1)), ans = n*(n+1)/2- l*(l+1)/2*(m+1),但有可能不能平均分配,就有(n-m)%(m+1)個點分配到了l+1個點,所以ans就還要再減去(l+1)*((n-m)%(m+1))
#include<bits/stdc++.h> using namespace std; #define lowbit(x) ((x)&(-x)) typedef long long LL; void run_case() { int n, m; cin >> n >> m; int k = (n-m)/(m+1); LL ans = 1LL*n*(n+1)/2-1LL*(k+1)*k/2*(m+1)-(k+1)*((n-m)%(m+1)); cout << ans << "\n"; } int main() { ios::sync_with_stdio(false), cin.tie(0); //cout.setf(ios_base::showpoint);cout.precision(10); int t; cin >> t; while(t--) run_case(); cout.flush(); return 0; }
