2016 湖南省赛 9/11

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;
}

K

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值