1 ≤ n ≤ 65000 1\le n\le 65000 1≤n≤65000 且 s s s 不包含 0 0 0
题解
∑ i = 1 n i [ s [ i ] 是 偶 数 ] \sum_{i=1}^ni[s[i]是偶数] i=1∑ni[s[i]是偶数]
代码
#include<bits/stdc++.h>// 20030830inlineintread(){
int res =0;bool bo =0;char c;while(((c =getchar())<'0'|| c >'9')&& c !='-');if(c =='-') bo =1;else res = c -48;while((c =getchar())>='0'&& c <='9')
res =(res <<3)+(res <<1)+(c -48);return bo ?~res +1: res;}typedeflonglong ll;constint N =1e5+5;int n;char s[N];
ll ans;intmain(){
n =read();scanf("%s", s +1);for(int i =1; i <= n; i++)if(s[i]-'0'+1&1) ans += i;
std::cout << ans << std::endl;return0;}
B
题意
一个长度为 n n n 的正整数数组 a a a
求一个长度为 n n n 的非负数组 x x x ,满足
(1)对于所有的 1 ≤ i ≤ n 1\le i\le n 1≤i≤n ,有 0 ≤ x i ≤ a i 0\le x_i\le a_i 0≤xi≤ai
(2)对于所有的 1 ≤ j < i ≤ n 1\le j<i\le n 1≤j<i≤n ,有 x j = 0 x_j=0 xj=0 或 x j < x i x_j<x_i xj<xi
(3)最大化 ∑ i = 1 n x i \sum_{i=1}^nx_i ∑i=1nxi
求这个最大值
1 ≤ n ≤ 2 × 1 0 5 1\le n\le 2\times10^5 1≤n≤2×105 , 1 ≤ a i ≤ 1 0 9 1\le a_i\le 10^9 1≤ai≤109
题解
从右到左考虑,显然每个 x i x_i xi 需要取到它能取到的最大值
也就是说
(1) x n = a n x_n=a_n xn=an
(2) x i = min ( a i , max ( 0 , x i + 1 − 1 ) ) x_i=\min(a_i,\max(0,x_{i+1}-1)) xi=min(ai,max(0,xi+1−1)) , 1 ≤ i < n 1\le i<n 1≤i<n
代码
#include<bits/stdc++.h>// 20030830inlineintread(){
int res =0;bool bo =0;char c;while(((c =getchar())<'0'|| c >'9')&& c !='-');if(c =='-') bo =1;else res = c -48;while((c =getchar())>='0'&& c <='9')
res =(res <<3)+(res <<1)+(c -48);return bo ?~res +1: res;}template<classT>inline T Min(const T &a,const T &b){
return a < b ? a : b;}typedeflonglong ll;constint N =2e5+5;int n, a[N], wt;
ll ans;intmain(){
n =read();for(int i =1; i <= n; i++) a[i]=read(); wt = a[n]+1;for(int i = n; i >=1; i--){
wt--;if(wt <0) wt =0;
wt =Min(wt, a[i]);
ans += wt;}
std::cout << ans << std::endl;return0;}
C
题意
一棵 n n n 个节点的树,边有红边和黑边
求有多少个节点序列 a 1 … k a_{1\dots k} a1…k
满足 a 1 a_1 a1 到 a 2 a_2 a2 , a 2 a_2 a2 到 a 3 a_3 a3 , … \dots … , a k − 1 a_{k-1} ak−1 到 a k a_k ak 这 k − 1 k-1 k−1 条路径中存在一条经过了至少一条黑边
2 ≤ n ≤ 1 0 5 2\le n\le10^5 2≤n≤105 , 2 ≤ k ≤ 100 2\le k\le100 2≤k≤100
题解
容易想到一个经典的 O(nk) 树形 DP
用总方案数 n k n^k nk 减掉不经过黑边的方案数
显然,如果只加入所有红边,那么不经过黑边的方案数,就是节点序列 a 1 … k a_{1\dots k} a1…k 中所有点位于同一个连通块内的方案数
用并查集维护连通块大小
答案就是 n k n^k nk 减去所有连通块的大小的 k k k 次幂之和
代码
#include<bits/stdc++.h>// 20030830inlineintread(){
int res =0;bool bo =0;char c;while(((c =getchar())<'0'|| c >'9')&& c !='-');if(c =='-') bo =1;else res = c -48;while((c =getchar())>='0'&& c <='9')
res =(res <<3)+(res <<1)+(c -48);return bo ?~res +1: res;}constint N =1e5+5, ZZQ =1e9+7;intqpow(int a,int b){
int res =1;while(b){
if(b &1) res =1ll* res * a % ZZQ;
a =1ll* a * a % ZZQ;
b >>=1;}return res;}int n, k, fa[N], sze[N], ans;intcx(int x){
if(fa[x]!= x) fa[x]=cx(fa[x]);return fa[x];}voidzm(int x,int y){
int ix =cx(x), iy =cx(y);if(ix != iy) fa[iy]= ix, sze[ix]+= sze[iy];}intmain(){
int x, y, z;
n =read(); k =read();for(int i =1; i <= n; i++) fa[i]= i, sze[i]=1;for(int i =1; i < n; i++){
x =read(); y =read