【AtCoder】AGC002

AGC002

A - Range Product

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define space putchar(' ')
#define enter putchar('\n')
#define eps 1e-10
#define MAXN 5005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef unsigned int u32;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;T f = 1;char c = getchar();
    while(c < '0' || c > '9') {
	if(c == '-') f = -1;
	c = getchar();
    }
    while(c >= '0' && c <= '9') {
	res = res * 10 +c - '0';
	c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar('-');}
    if(x >= 10) {
	out(x / 10);
    }
    putchar('0' + x % 10);
}
int a,b;
void Solve() {
    read(a);read(b);
    if(b >= 0 && a <= 0) puts("Zero");
    else if(a > 0) {
	puts("Positive");
    }
    else {
	if((b - a + 1) & 1) puts("Negative");
	else puts("Positive");
    }
}

int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Solve();
    return 0;
}

B - Box and Ball

如果一个地方的球空了把可能有红球标成0,剩下的在转移时如果从一个可能有红球的盒子里转移过来则认为这个盒子里可能有红球

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define space putchar(' ')
#define enter putchar('\n')
#define eps 1e-10
#define MAXN 100005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef unsigned int u32;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;T f = 1;char c = getchar();
    while(c < '0' || c > '9') {
	if(c == '-') f = -1;
	c = getchar();
    }
    while(c >= '0' && c <= '9') {
	res = res * 10 +c - '0';
	c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar('-');}
    if(x >= 10) {
	out(x / 10);
    }
    putchar('0' + x % 10);
}
int N,M,ct[MAXN],cnt[MAXN];
void Solve() {
    read(N);read(M);
    for(int i = 1 ; i <= N ; ++i) cnt[i] = 1;
    ct[1] = 1;
    int x,y;
    for(int i = 1 ; i <= M ; ++i) {
	read(x);read(y);
	cnt[x]--;cnt[y]++;
	if(ct[x]) {
	    ct[y] = 1;
	}
	if(cnt[x] == 0) ct[x] = 0;
    }
    int ans = 0;
    for(int i = 1 ; i <= N ; ++i) {
	ans += ct[i];
    }
    out(ans);enter;
}

int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Solve();
    return 0;
}

C - Knot Puzzle

如果存在两端相邻的相加大于等于L,那么不断删掉两端可以成立

同时这也是必要的

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define space putchar(' ')
#define enter putchar('\n')
#define eps 1e-10
#define MAXN 100005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef unsigned int u32;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;T f = 1;char c = getchar();
    while(c < '0' || c > '9') {
	if(c == '-') f = -1;
	c = getchar();
    }
    while(c >= '0' && c <= '9') {
	res = res * 10 +c - '0';
	c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar('-');}
    if(x >= 10) {
	out(x / 10);
    }
    putchar('0' + x % 10);
}
int N,a[MAXN];
int64 L,sum;
vector<int> ans;
void Solve() {
    read(N);read(L);
    for(int i = 1 ; i <= N ; ++i) {read(a[i]);}
    for(int i = 1 ; i < N ; ++i) {
	if(a[i] + a[i + 1] >= L) {
	    puts("Possible");
	    for(int j = 1 ; j < i ; ++j) ans.pb(j);
	    for(int j = N - 1 ; j > i ; --j) ans.pb(j);
	    ans.pb(i);
	    for(auto t : ans) {
		out(t);enter;
	    }
	    return;
	}
    }
    puts("Impossible");
}

int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Solve();
    return 0;
}

D - Stamp Rally

kruskal会有一个生成树,就是每条边新建一个点,代表这个联通块,这个生成树的叶子是原来的节点

然后二分最小的边,两个点同时找到树上的大于等于这条边的那个祖先

如果相同的话看看这个子树里的值是否大于z,否则看看两个子树里的值是否大于z

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define space putchar(' ')
#define enter putchar('\n')
#define eps 1e-10
#define MAXN 400005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef unsigned int u32;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;T f = 1;char c = getchar();
    while(c < '0' || c > '9') {
	if(c == '-') f = -1;
	c = getchar();
    }
    while(c >= '0' && c <= '9') {
	res = res * 10 +c - '0';
	c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar('-');}
    if(x >= 10) {
	out(x / 10);
    }
    putchar('0' + x % 10);
}
int Ncnt,N,M,head[MAXN],sumE,Q;
int bel[MAXN],val[MAXN],siz[MAXN],fa[MAXN][20];
vector<int> to[MAXN];
int getfa(int x) {
    return bel[x] == x ? x : bel[x] = getfa(bel[x]);
}
void dfs(int u) {
    if(u <= N) siz[u]++;
    for(auto t : to[u]) {
	fa[t][0] = u;
	dfs(t);
	siz[u] += siz[t];
    }
    
}
void Solve() {
    read(N);read(M);
    Ncnt = N;
    int a,b;
    for(int i = 1 ; i <= N + M ; ++i) bel[i] = i;
    for(int i = 1 ; i <= M ; ++i) {
	read(a);read(b);
	if(getfa(a) != getfa(b)) {
	    ++Ncnt;
	    to[Ncnt].pb(getfa(a));to[Ncnt].pb(getfa(b));
	    bel[getfa(a)] = Ncnt;
	    bel[getfa(b)] = Ncnt;
	    val[Ncnt] = i;
	}
    }
    dfs(Ncnt);
    for(int j = 1 ; j <= 19 ; ++j) {
	for(int i = 1 ; i <= Ncnt ; ++i) {
	    fa[i][j] = fa[fa[i][j - 1]][j - 1];
	}
    }
    read(Q);
    int x,y,z;
    val[0] = M + 1;
    for(int i = 1 ; i <= Q ; ++i) {
	read(x);read(y);read(z);
	int L = 1,R = M;
	while(L < R) {
	    int a = x,b = y;
	    int mid = (L + R) >> 1;
	    for(int j = 19 ; j >= 0 ; --j) {
		if(val[fa[a][j]] <= mid) a = fa[a][j];
		if(val[fa[b][j]] <= mid) b = fa[b][j];
 	    }
	    int res = 0;
	    if(a == b) res += siz[a];
	    else res += siz[a] + siz[b];
	    if(res >= z) R = mid;
	    else L = mid + 1;
	}
	out(L);enter;
    }
}

int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Solve();
    return 0;
}

E - Candy Piles

有点神仙的博弈题

就是把这些数从大到小排序,画出轮廓线,放到平面直角坐标系里,轮廓线上的点都是必胜态,轮廓线凸角的下面都是必败态,必败态的左和下是必胜态

每个必败态会形成一个对角线,看看(0,0)在哪两个对角线之间,对角线相遇的地方是一个下凹的拐点,这个拐点是必胜态,看看0,0在这条线左边还是右边,左边就是左边的必败态控制,右边就是右边的必败态控制

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define space putchar(' ')
#define enter putchar('\n')
#define eps 1e-10
#define MAXN 100005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef unsigned int u32;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;T f = 1;char c = getchar();
    while(c < '0' || c > '9') {
	if(c == '-') f = -1;
	c = getchar();
    }
    while(c >= '0' && c <= '9') {
	res = res * 10 +c - '0';
	c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar('-');}
    if(x >= 10) {
	out(x / 10);
    }
    putchar('0' + x % 10);
}
int N;
int a[MAXN];
vector<pii > p;
void Solve() {
    read(N);
    for(int i = 1 ; i <= N ; ++i) read(a[i]);
    sort(a + 1,a + N + 1,[](int c,int d){return c > d;});
    for(int i = 1 ; i <= N ; ++i) {
	if(a[i + 1] != a[i]) {
	    p.pb(mp(i,i - a[i]));
	}
    }
    int c = -1,d = p.size();
    
    while(c < (int)p.size() - 1 && p[c + 1].se <= 0) ++c;
    while(d > 0 && p[d - 1].se >= 0) --d;
    if(c >= 0) {
	if(p[c].se == 0) {puts("Second");return;}
    }
    bool f = 0;
    if(c >= 0 && d < (int)p.size()) {
	if(!((abs(p[c].se) ^ abs(p[d].se)) & 1)) {
	    f = (abs(p[c].se) & 1);
	}
	else {
	    int t = p[c].fi - a[p[c].fi + 1];
	    if(t == 0) f = 1;
	    else if(0 < t) {f |= abs(p[c].se) & 1;}
	    else f |= abs(p[d].se) & 1;
	}
    }
    else if(c >= 0) { f |= abs(p[c].se) & 1;}
    else if(d < (int)p.size()) {f |= p[d].se & 1;}
    if(f) puts("First");
    else puts("Second");
}

int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Solve();
    return 0;
}

F - Leftmost Ball

倒着做就行了,每次在队首新加一个0,然后选择一种颜色填上

要求补充不漏的话,我们必须要求这个颜色的第一个在之前一种颜色的前面

只要用dp记录一下前一个颜色的位置就可以了

状态是\(n^2\)的的,用前缀和优化一下转移是\(O(1)\)的,可以通过

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define space putchar(' ')
#define enter putchar('\n')
#define eps 1e-10
#define MAXN 100005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef unsigned int u32;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;T f = 1;char c = getchar();
    while(c < '0' || c > '9') {
	if(c == '-') f = -1;
	c = getchar();
    }
    while(c >= '0' && c <= '9') {
	res = res * 10 +c - '0';
	c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar('-');}
    if(x >= 10) {
	out(x / 10);
    }
    putchar('0' + x % 10);
}
const int MOD = 1000000007;
int fac[10000005],invfac[10000005];
int dp[2005][2005],N,K,sum[2005];
int inc(int a,int b) {
    return a + b >= MOD ? a + b - MOD : a + b;
}
int mul(int a,int b) {
    return 1LL * a * b % MOD;
}
void update(int &x,int y) {
    x = inc(x,y);
}
int C(int n,int m) {
    if(n < m) return 0;
    return mul(fac[n],mul(invfac[m],invfac[n - m]));
}
int Query(int n,int m) {
    return C(n + m - 1,m - 1);
}
int fpow(int x,int c) {
    int res = 1,t = x;
    while(c) {
	if(c & 1) res = mul(res,t);
	t = mul(t,t);
	c >>= 1;
    }
    return res;
}
void Solve() {
    read(N);read(K);
    if(K == 1) {puts("1");return;}
    fac[0] = 1;
    for(int i = 1 ; i <= 10000000 ; ++i) fac[i] = mul(fac[i - 1],i);
    invfac[10000000] = fpow(fac[10000000],MOD - 2);
    for(int i = 9999999 ; i >= 0 ; --i) invfac[i] = mul(invfac[i + 1],i + 1);
    dp[1][0] = 1;
    for(int i = 2 ; i <= N ; ++i) {
	int t = (i - 1) * K + 1;
	for(int j = N ; j >= 0 ; --j) sum[j] = inc(sum[j + 1],dp[i - 1][j]);
	for(int j = 0 ; j <= i ; ++j) {
	    update(dp[i][j],mul(sum[max(0,j - 1)],Query(K - 2,t - j)));
	}
    }
    int ans = 0;
    for(int j = 0 ; j <= N ; ++j) update(ans,mul(dp[N][j],fac[N]));
    out(ans);enter;
}

int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Solve();
    return 0;
}
posted @ 2019-05-23 09:09  sigongzi  阅读(290)  评论(0编辑  收藏  举报