第二场纳新赛
C.天天乐乐
每个任务花\(c_i\)完成,在时间\(t\)完成,得到价值\(a_i - t * b_i\)
按bi从大到小排序,然后看哪个选不选, f[i][j]表示前i个,j的时间最多的价值
F.字符串
找所有的子串s(l,r),使s(1, r - l + 1) = s(l:r)
J.幂次
赛时的题,\(l,r<=1e18\) 求 \(f(l, r)\)也就是calc(r)的过程中到l就停止
The 23rd Sichuan University Programming Contest D.MISagain
calc(y) = sum以y为右端点的区间的|S|
calc(y) = calc(2^(k + 1) - y - 1) + 段间 + 本段内
+ 段间长度 * 后缀最大值(不能取段间的数,都和后面的|S|一样) + 段内等差
#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define ft first
#define se second
#define yes cout << "Yes\n"
#define no cout << "No\n"
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
typedef long double ld;
typedef long long ll;
typedef __int128 LL;
typedef pair<int, int> pii;
int n;
const int V = 500005;
int lst[V];
ll f[V];
ll calc(int y, int sum){
if(y <= 0) return 0;
int len = y - lst[y] + 1;
ll ret = 1ll * (sum + 1 + sum + len) * len / 2;
sum += (y - lst[y] + 1);
ret += 1ll * sum * max(0, lst[y] - (lst[y] * 2 - y));
ret += calc(lst[y] * 2 - y - 1, sum);
return ret;
}
void init(){
for(int i = 1; i < V; i *= 2) lst[i] = i;
for(int i = 1; i < V; i ++) if(!lst[i]) lst[i] = lst[i - 1];
for(int i = 1; i < V; i ++) f[i] = calc(i, 0);
for(int i = 1; i < V; i ++) f[i] += f[i - 1];
}
void solve(){
cin >> n;
cout << f[n] << '\n';
}
signed main()
{
std::ios::sync_with_stdio(false);
init();
int T = 1;
cin >> T;
while(T -- ){
solve();
}
}

浙公网安备 33010602011771号