emmm也是有点没打好的场。其实题都会,但是没写完。
A
这题卡了我们挺久的。。。实际上直接对两边的数mod 2016按余数分类就行。
但是我第一反应容斥x
直接跑偏,不过容斥还是可以过的!
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstdint>
#include <cstdio>
const int MOD = 2016;
using i64 = int64_t;
std::vector<int> get_fs () {
auto v = std::vector<int>();
for (int i = 1; i <= MOD; ++i)
if (MOD % i == 0)
v.push_back(i);
return v;
}
i64 cnt_exc (i64 x, i64 f) {
return
x / f
- x / (f * 2)
- x / (f * 3)
- x / (f * 7)
+ x / (f * 2 * 3)
+ x / (f * 2 * 7)
+ x / (f * 3 * 7)
- x / (f * 2 * 3 * 7);
}
int main() {
std::ios::sync_with_stdio(false);
auto fs = get_fs();
int n, m;
while (std::cin >> n >> m) {
if (n > m)
std::swap(n, m);
i64 ans = 0;
for (i64 a = 1; a <= n; a *= 2)
for (i64 b = 1; a * b <= n; b *= 3)
for (i64 c = 1; a * b * c <= n; c *= 7) {
i64 ra = std::max((i64)1, 32 / a),
rb = std::max((i64)1, 9 / b),
rc = std::max((i64)1, 7 / c);
i64 c1 = cnt_exc(n, a * b * c);
i64 c2 = m / (ra * rb * rc);
ans += c1 * c2;
}
std::cout << ans << '\n';
}
return 0;
}
B
直接DP
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
using ll = long long;
int const N = 100005;
int const MOD = 1e9 + 7;
int a[N], b[N];
int du[N];
ll f[N];
int n, m;
vector<int> G[N];
int main() {
ios::sync_with_stdio(0);
while (cin >> n >> m) {
for (int i = 1; i <= n; ++i) {
cin >> a[i] >> b[i];
du[i] = f[i] = 0;
}
for (int i = 1; i <= m; ++i) {
int x, y;
cin >> x >> y;
G[x].push_back(y);
du[y]++;
}
auto Q = queue<int>();
for (int i = 1; i <= n; ++i)
if (du[i] == 0)
Q.push(i);
while (Q.empty() == 0) {
int now = Q.front();
Q.pop();
for (auto c : G[now]) {
f[c] += f[now] + a[now];
f[c] %= MOD;
du[c]--;
if (du[c] == 0)
Q.push(c);
}
}
ll ans = 0;
for (int i = 1; i <= n; ++i) {
ans = (ans + b[i] * f[i] % MOD) % MOD;
G[i].clear();
}
cout << ans << '\n';
}
}
C
考虑BEST定理,然后就是定向问题了,直接用矩阵树定理搞搞就行。
但是比赛的时候忘记了这两个定理是无向图还是有向图,有重边的时候又应该怎么搞。。
于是各种try
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <cstdlib>
using namespace std;
using ll = long long;
int const N = 200005;
int const MOD = 1e9 + 7;
ll const inv2 = (MOD + 1) / 2;
ll KSM(ll a, ll k) {
ll ret = 1;
for (; k; k >>= 1, a = a * a % MOD)
if (k & 1)
ret = ret * a % MOD;
return ret;
}
ll fac[N], fac_inv[N];
ll C(int n, int m) {
return fac[n] * fac_inv[m] % MOD * fac_inv[n - m] % MOD;
}
int main() {
fac[0] = fac_inv[0] = 1;
for (int i = 1; i < N; ++i)
fac[i] = 1ll * fac[i - 1] * i % MOD;
for (int i = 1; i < N; ++i)
fac_inv[i] = KSM(fac[i], MOD - 2);
ios::sync_with_stdio(0);
int a, b, c;
while (cin >> a >> b >> c) {
ll du1 = a + b, du2 = a + c, du3 = b + c;
if ((du1 & 1) || (du2 & 1) || (du3 & 1)) {
cout << 0 << '\n';
continue;
}
ll ans = 0;
ll dum = fac[du1 / 2 - 1] * fac[du2 / 2 - 1] % MOD * fac[du3 / 2 - 1] % MOD;
for (int i = 0; i <= a; ++i) {
int x = (b - a) / 2 + i;
int y = (c - a) / 2 + i;
if (x < 0 || b - x < 0 || y < 0 || c - y < 0)
continue;
ll mat = std::abs(1ll * (du2 / 2) * (du3 / 2) - 1ll * y * (c - y));
mat %= MOD;
ll Cm = C(a, i) * C(c, y) % MOD * C(b, x) % MOD;
// cerr << i << ' ' << x << ' ' << y << " : " << mat << ' ' << Cm << ' ' << dum << '\n';
// cerr << du2 / 2 << ' ' << du3 / 2 << ' ' << c << ' ' << c - y << '\n';
ans = (ans + Cm * mat % MOD * dum % MOD) % MOD;
}
ans = ans * du1 % MOD * inv2 % MOD;
ans = (ans + MOD) % MOD;
cout << ans << '\n';
}
}
D
E
小洛洛一发过了,tql
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstdint>
#include <cinttypes>
using i64 = int64_t;
i64 cnts (int n) {
return (i64)(n - 1) * (n - 1);
}
i64 solve (std::vector<int> const &v) {
int n = v.size();
int shl1 = -1, shl2 = -1;
int shr1 = -1, shr2 = -1;
int other = -1;
for (int i = 0; i < n; ++i) {
if (v[i] == 0 || v[i] == i + 1)
;
else if (v[i] == i + 1 - 1) {
if (shl1 == -1)
shl1 = i;
shl2 = i;
} else if (v[i] == i + 1 + 1) {
if (shr1 == -1)
shr1 = i;
shr2 = i;
} else {
if (other == -1)
other = i;
else
return 0;
}
}
//fprintf(stderr, "l=[%d,%d] r=[%d,%d] oth=%d\n", shl1, shl2, shr1, shr2, other);
if (shl1 != -1)
for (int i = shl1; i <= shl2; ++i)
if (v[i] == i + 1)
return 0;
if (shr1 != -1)
for (int i = shr1; i <= shr2; ++i)
if (v[i] == i + 1)
return 0;
//fprintf(stderr, "> 1\n");
i64 ans = 0;
if (other != -1) {
if (other < v[other] - 1)
return (shl1 == -1 || (other < shl1 && shl2 <= v[other] - 1))
&& shr1 == -1;
else
return shl1 == -1
&& (shr1 == -1 || (v[other] - 1 <= shr1 && shr2 < other));
} else if (shl1 != -1 && shr1 != -1) {
return shl1 == shl2 && shr1 == shr2 && shl1 - 1 == shr1;
} else if (shl1 == -1 && shr1 == -1) {
int len = 0;
for (auto x: v)
if (x == 0)
++len;
else {
if (len > 0)
ans += cnts(len);
len = 0;
}
if (len > 0)
ans += cnts(len);
} else if (shl1 != -1) {
int l0 = 0, r0 = 1;
for (int i = shl1 - 1; i >= 0 && v[i] == 0; --i)
++l0;
for (int i = shl2 + 1; i < n && v[i] == 0; ++i)
++r0;
ans = (i64)l0 * r0;
} else { // shr1 != -1
int l0 = 1, r0 = 0;
for (int i = shr1 - 1; i >= 0 && v[i] == 0; --i)
++l0;
for (int i = shr2 + 1; i < n && v[i] == 0; ++i)
++r0;
ans = (i64)l0 * r0;
}
return ans;
}
int main () {
int n;
while (scanf("%d", &n) == 1) {
auto v = std::vector<int>(n);
for (auto &c: v)
scanf("%d", &c);
i64 ans = solve(v);
printf("%" PRId64 "\n", ans);
}
return 0;
}
F
又是小洛洛和新队友一起做的。
#include <iostream>
#include <limits>
#include <cinttypes>
#include <cstdint>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <queue>
using i64 = int64_t;
struct Graph {
struct E {
int to;
i64 w;
bool operator< (E const &rhs) const {
return w > rhs.w; // min heap
}
};
int n;
std::vector<std::vector<E>> e;
Graph (int n_): n(n_), e(n_) {}
void adde (int a, int b, i64 t) {
e[a].push_back({ b, t });
//fprintf(stderr, "> %d -> %d (%" PRId64 ")\n", a, b, t);
}
i64 dijk (int ibeg, int iend) const {
const i64 INF = std::numeric_limits<i64>::max();
auto dis = std::vector<i64>(n, INF);
auto q = std::priority_queue<E>();
q.push({ ibeg, 0 });
while (!q.empty()) {
auto cur = q.top();
q.pop();
if (dis[cur.to] != INF)
continue;
dis[cur.to] = cur.w;
for (auto &to: e[cur.to])
if (dis[to.to] == INF)
q.push({ to.to, cur.w + to.w });
}
return dis[iend];
}
};
struct QE {
int to;
int c;
int n1, n2;
i64 w;
bool operator< (QE const &rhs) const {
return c < rhs.c;
}
};
int main () {
int n, m;
while (scanf("%d%d", &n, &m) == 2) {
auto g = Graph(0);
int n2 = 2;
{
auto qe = std::vector<std::vector<QE>>(n);
for (int i = 0; i < m; ++i) {
int a, b, c, t;
scanf("%d%d%d%d", &a, &b, &c, &t);
--a, --b;
int a2 = n2++, b2 = n2++;
qe[a].push_back({ b, c, a2, b2, (i64)t });
qe[b].push_back({ a, c, b2, a2, (i64)t });
}
g = Graph(n2);
for (int i = 0; i < n; ++i) {
int ne = qe[i].size();
auto &cq = qe[i];
std::sort(std::begin(cq), std::end(cq));
for (auto &to: cq)
g.adde(to.n1, to.n2, to.w);
for (int j = 1; j < ne; ++j) {
int dc = cq[j].c - cq[j - 1].c;
g.adde(cq[j - 1].n2, cq[j].n2, dc);
g.adde(cq[j].n2, cq[j - 1].n2, dc);
}
}
for (auto &to: qe[0])
g.adde(0, to.n2, 0);
for (auto &to: qe[n - 1])
g.adde(to.n2, 1, 0);
}
i64 ans = g.dijk(0, 1);
printf("%" PRId64 "\n", ans);
}
return 0;
}
G
区间最值就行。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
int const N = 100005;
int const INF = 1e9;
int a[N], s[N];
int mx[N << 2];
int n, m;
char str[N];
void build(int k, int l, int r) {
if (l == r) {
mx[k] = s[l];
return;
}
int mid = (l + r) >> 1;
build(k << 1, l, mid);
build(k << 1 | 1, mid + 1, r);
mx[k] = min(mx[k << 1], mx[k << 1 | 1]);
}
int query(int k, int l, int r, int ql, int qr) {
if (ql <= l && r <= qr)
return mx[k];
int mid = (l + r) >> 1, ret = INF;
if (ql <= mid)
ret = query(k << 1, l, mid, ql, qr);
if (qr > mid)
ret = min(ret, query(k << 1 | 1, mid + 1, r, ql, qr));
return ret;
}
int main() {
ios::sync_with_stdio(0);
while (cin >> n >> m) {
cin >> (str + 1);
for (int i = 1; i <= n; ++i)
s[i] = s[i - 1] + (str[i] == '(' ? 1 : -1);
build(1, 1, n);
for (int o = 0; o < m; ++o) {
int l, r;
cin >> l >> r;
if (l > r)
swap(l, r);
bool ans = 1;
if (str[l] == '(' && str[r] == ')')
ans = query(1, 1, n, l, r - 1) >= 2;
if (ans)
cout << "Yes" << '\n';
else
cout << "No" << '\n';
}
}
}
H
大力算每一位的贡献就行。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;
using ll = long long;
int const N = 100005;
int const MOD = 1e9 + 7;
ll s[N];
ll bit10[N];
ll f[N], g[N];
int a[N];
int n;
char str[N];
ll get_sum(int l, int r) {
if (l > r)
return 0;
return (s[r] - s[l - 1] + MOD) % MOD;
}
int main() {
ios::sync_with_stdio(0);
while (cin >> n) {
cin >> (str + 1);
for (int i = 1; i <= n; ++i)
a[i] = str[i] - '0';
bit10[n] = 1;
for (int i = n - 1; i >= 1; --i)
bit10[i] = bit10[i + 1] * 10ll % MOD;
for (int i = 1; i <= n; ++i)
s[i] = (s[i - 1] + bit10[i]) % MOD;
ll sum = 0, si = 0;
ll total = 1ll * n * (n - 1) / 2 + n;
for (int i = 1; i <= (n + 1) / 2; ++i) {
f[i] = sum + get_sum(i + 1, n - i + 1) * i % MOD;
f[n - i + 1] = sum + get_sum(i, n - i) * i % MOD;
sum = (sum + 1ll * (bit10[i] + bit10[n - i + 1]) * i) % MOD;
g[n - i + 1] = g[i] = total - si - (n - i - i + 1) * i;
si += i * 2;
}
ll ans = 0;
for (int i = 1; i <= n; ++i)
ans = (ans + f[i] * a[i] % MOD + (g[i] % MOD) * (a[i] * bit10[i] % MOD) % MOD) % MOD;
cout << ans << '\n';
}
}
I
dsu on tree一下,然后map搞颜色就行。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <map>
#include <utility>
#include <vector>
using namespace std;
int const N = 100005;
struct edge {
int x, y;
} b[N];
int a[N], n;
int id[N];
int ans[N];
int siz[N], son[N], fa[N];
map<int, int> col_mp;
vector<int> G[N];
void dfs(int x, int pre) {
fa[x] = pre;
int mxt = -1;
siz[x] = 1;
col_mp[a[x]]++;
for (auto y : G[x]) {
if (y == pre)
continue;
dfs(y, x);
siz[x] += siz[y];
if (siz[y] > mxt) {
mxt = siz[y];
son[x] = y;
}
}
}
inline void add(int c, map<int, int>& mp, int& anss) {
mp[c]++;
int now = mp[c], tot = col_mp[c];
if (tot == 1)
return;
if (now == 1)
++anss;
if (now == tot)
--anss;
}
void work_oth(int x, map<int, int>& mp, int& anss) {
add(a[x], mp, anss);
for (auto y : G[x]) {
if (y == fa[x])
continue;
work_oth(y, mp, anss);
}
}
void work(int x, map<int, int>& mp, int& anss) {
if (son[x])
work(son[x], mp, anss);
add(a[x], mp, anss);
for (auto y : G[x]) {
if (y == fa[x] || y == son[x])
continue;
auto tmp = map<int, int>();
int tans = 0;
work(y, tmp, tans);
work_oth(y, mp, anss);
}
if (id[x])
ans[id[x]] = anss;
}
int main() {
ios::sync_with_stdio(0);
while (cin >> n) {
col_mp.clear();
for (int i = 1; i <= n; ++i)
cin >> a[i];
for (int i = 1; i < n; ++i) {
int x, y;
cin >> x >> y;
b[i].x = x, b[i].y = y;
G[x].push_back(y);
G[y].push_back(x);
}
dfs(1, 0);
for (int i = 1; i < n; ++i) {
int x = b[i].x, y = b[i].y;
if (fa[x] == y)
id[x] = i;
else
id[y] = i;
}
auto tmp = map<int, int>();
int tans = 0;
work(1, tmp, tans);
for (int i = 1; i < n; ++i)
cout << ans[i] << '\n';
for (int i = 1; i <= n; ++i) {
ans[i] = 0;
G[i].clear();
son[i] = 0;
}
}
}
J
直接上了凸多边形交的板子XDDDDD
#include <cstdio>
#include <cstring>
#include <cmath>
const int maxisn=16;
const double eps=1e-10;
const double pi=acos(-1.0);
int dcmp(double x){
if(x>eps) return 1;
return x<-eps ? -1 : 0;
}
inline double Sqr(double x){
return x*x;
}
struct Point{
double x,y;
Point(){x=y=0;}
Point(double _x,double _y):x(_x),y(_y){};
friend Point operator + (const Point &a,const Point &b) {
return Point(a.x+b.x,a.y+b.y);
}
friend Point operator - (const Point &a,const Point &b) {
return Point(a.x-b.x,a.y-b.y);
}
friend bool operator == (const Point &a,const Point &b) {
return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;
}
friend Point operator * (const Point &a,const double &b) {
return Point(a.x*b,a.y*b);
}
friend Point operator * (const double &a,const Point &b) {
return Point(a*b.x,a*b.y);
}
friend Point operator / (const Point &a,const double &b) {
return Point(a.x/b,a.y/b);
}
friend bool operator < (const Point &a, const Point &b) {
return a.x < b.x || (a.x == b.x && a.y < b.y);
}
inline double dot(const Point &b)const{
return x*b.x+y*b.y;
}
inline double cross(const Point &b,const Point &c)const{
return (b.x-x)*(c.y-y)-(c.x-x)*(b.y-y);
}
};
Point LineCross(const Point &a,const Point &b,const Point &c,const Point &d){
double u=a.cross(b,c),v=b.cross(a,d);
return Point((c.x*v+d.x*u)/(u+v),(c.y*v+d.y*u)/(u+v));
}
double PolygonArea(Point p[],int n){
if(n<3) return 0.0;
double s=p[0].y*(p[n-1].x-p[1].x);
p[n]=p[0];
for(int i=1;i<n;i++){
s+=p[i].y*(p[i-1].x-p[i+1].x);
}
return fabs(s*0.5);
}
double CPIA(Point a[],Point b[],int na,int nb){
Point p[maxisn],temp[maxisn];
int i,j,tn,sflag,eflag;
a[na]=a[0],b[nb]=b[0];
memcpy(p,b,sizeof(Point)*(nb+1));
for(i=0;i<na&&nb>2;++i){
sflag=dcmp(a[i].cross(a[i+1],p[0]));
for(j=tn=0;j<nb;++j,sflag=eflag){
if(sflag>=0) temp[tn++]=p[j];
eflag=dcmp(a[i].cross(a[i+1],p[j+1]));
if((sflag^eflag)==-2)
temp[tn++]=LineCross(a[i],a[i+1],p[j],p[j+1]);
}
memcpy(p,temp,sizeof(Point)*tn);
nb=tn,p[nb]=p[0];
}
if(nb<3) return 0.0;
return PolygonArea(p,nb);
}
int main () {
int x1, y1, x2, y2, x3, y3, x4, y4;
while (scanf("%d%d%d%d%d%d%d%d", &x1, &y1, &x2, &y2, &x3, &y3, &x4, &y4) == 8) {
Point p1[4], *q = p1;
*q++ = { x1, y1 };
if ((x1 < x2) == (y1 < y2)) {
*q++ = { x2, y1 };
*q++ = { x1, y2 };
} else {
*q++ = { x1, y2 };
*q++ = { x2, y1 };
}
Point p2[5];
q = p2;
*q++ = { x3, y3 };
*q++ = { x4, y3 };
*q++ = { x4, y4 };
*q++ = { x3, y4 };
printf("%.8f\n", CPIA(p1, p2, 3, 4));
}
return 0;
}