【AtCoder】CODE FESTIVAL 2016 qual C

CODE FESTIVAL 2016 qual C

A - CF

……

#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);
}
string s;
void Solve() {
    cin >> s;
    bool f = 0;
    for(int i = s.length() - 1 ; i >= 0 ; --i) {
	if(s[i] == 'F') f = 1;
	if(s[i] == 'C' && f) {
	    puts("Yes");return;
	}
    }
    puts("No");
}

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

B - K個のケーキ / K Cakes

找到最多的一天个数是m,如果m > K - m答案就是2m - K - 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);
}
int K,T,a[105];
void Solve() {
    read(K);read(T);
    int m = 0;
    for(int i = 1 ; i <= T ; ++i) {
	read(a[i]);
	m = max(a[i],m);
    }
    if(K - m >= m) {puts("0");return;}
    else {out(m - (K - m) - 1);enter;}
    
}

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

C - 二人のアルピニスト / Two Alpinists

如果是最大值变化的地方,那么必然是个固定值,我们判断如果两个都固定了某值,这两个值相不相等,如果只有一个地方固定了,那么看看满不满足另一边的条件

如果都没固定就是这个位置两边最大值较小的那个及以下都可以实现

#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 T[MAXN],A[MAXN];
int N;
int mul(int a,int b) {
    return 1LL * a * b % MOD;
}
void Solve() {
    read(N);
    for(int i = 1 ; i <= N ; ++i) read(T[i]);
    for(int i = 1 ; i <= N ; ++i) read(A[i]);
    int ans = 1;
    for(int i = 1 ; i <= N ; ++i) {
	if(T[i] != T[i - 1] || A[i] != A[i + 1]) {
	    int a = -1,b = -1;
	    if(T[i] != T[i - 1]) a = T[i];
	    if(A[i] != A[i + 1]) b = A[i];
	    if(a != -1 && b != -1) {
		if(a != b) {puts("0");return;}
	    }
	    if(b > T[i]) {puts("0");return;}
	    if(a > A[i]) {puts("0");return;}
	}
	else {
	    ans = mul(ans,min(A[i],T[i]));
	}
    }
    out(ans);enter;
}

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

D - Friction

如果只有两列,设\(dp[i][j]\)为第一列下移了i第二列下移了j

转移是\(dp[i][j] = min(dp[i - 1][j] + cost[i - 1][j],dp[i][j - 1] + cost[i][j - 1])\)

\(cost[i][j]\)可以用\(H^2\)求出,先暴力求出所有某一维为0的大小,然后从\(cost[i - 1][j - 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 500005
//#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);
}
int64 dp[305][305],ans,cost[305][305];
int H,W;
char s[305][305];
void Solve() {
    read(H);read(W);
    for(int i = 1 ; i <= H ; ++i) scanf("%s",s[i] + 1);
    for(int i = 1 ; i < W ; ++i) {
	for(int j = 0 ; j <= H ; ++j) {
	    for(int h = 0 ; h <= H ; ++h) {
		dp[j][h] = 1e18;
	    }
	}
	dp[0][0] = 0;
	memset(cost,0,sizeof(cost));
	for(int j = 0 ; j <= H ; ++j) {
	    int p1 = H - j,p2 = H;
	    while(p1 >= 1 && p2 >= 1) {
		if(s[p1][i] == s[p2][i + 1]) ++cost[j][0];
		--p1;--p2;
	    }
	}
	for(int j = 1 ; j <= H ; ++j) {
	    int p1 = H,p2 = H - j;
	    while(p1 >= 1 && p2 >= 1) {
		if(s[p1][i] == s[p2][i + 1]) ++cost[0][j];
		--p1;--p2;
	    }
	}
	for(int j = 1 ; j <= H ; ++j) {
	    for(int h = 1 ; h <= H ; ++h) {
		cost[j][h] = cost[j - 1][h - 1] - (s[H - j + 1][i] == s[H - h + 1][i + 1]);
	    }
	}
	for(int j = 0 ; j <= H * 2 ; ++j) {
	    for(int h = 0 ; h <= min(j,H) ; ++h) {
		int a = h,b = j - h;
		if(a > H || b > H) continue;
		int c = cost[a][b];
		if(a + 1 <= H) {
		    dp[a + 1][b] = min(dp[a + 1][b],dp[a][b] + c);
		}
		if(b + 1 <= H) {
		    dp[a][b + 1] = min(dp[a][b + 1],dp[a][b] + c);
		}
	    }
	}
	ans += dp[H][H];
    }
    out(ans);enter;
}

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

E - 順列辞書 / Encyclopedia of Permutations

如果对于一个位置\(s_{i}\)我们这个排列能乘上的数就是

\((s_i - 1 - \sum_{j = 1}^{i - 1}(s_j < s_{i}))(N - i)!\)

忽略掉\((N - i)!\),我们对每个\(i\)统计括号里面的总和是多少

我们分开,统计对于位置i,有多少种排列,\(s_j\)小于\(s_i\)的个数和

然后加上所有排列的\(s_{i} - 1\)

前一项很好统计,设空的位置个数为\(K\),那么如果这一位有了一个数

答案就是\((p[i] - 1)K!\)

如果没有数,就是所有未填的数 - 1的总和\(sum\)

答案是\(sum(K - 1)!\)

第二项分开考虑

如果这一位是空位,那么j可以是一个有数的地方,这个时候是空位大于j的方案数,可以用一个前缀变量记一下

如果j没有数,就是在K个数里选2个,剩下任填的方案

如果这一位不是空位,\(j\)有数,那么只要用树状数组维护比\(p_i\)小且在i以前的\(p_j\)有多少个

如果\(j\)没数,就是在未填的数中选一个\(p_i\)小的数,然后填在\(j\)那里,剩下\(K - 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 500005
//#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 N;
int fac[MAXN],invfac[MAXN],p[MAXN],s[MAXN],k;
int tr[MAXN],ans[MAXN];
bool vis[MAXN];
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;
}
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;
}
int C(int n,int m) {
    if(n < m) return 0;
    return mul(fac[n],mul(invfac[m],invfac[n - m]));
}
int lowbit(int x) {return x & (-x);}
void insert(int x,int c) {
    while(x <= N) {
	tr[x] = inc(tr[x],c);
	x += lowbit(x);
    }
}
int query(int x) {
    int r = 0;
    while(x > 0) {
	r = inc(r,tr[x]);
	x -= lowbit(x);
    }
    return r;
}
void update(int &x,int y) {
    x = inc(x,y);
}
void Solve() {
    read(N);
    fac[0] = 1;
    for(int i = 1 ; i <= N ; ++i) {
	fac[i] = mul(fac[i - 1],i); 
    }
    invfac[N] = fpow(fac[N],MOD - 2);
    for(int i = N - 1 ; i >= 0 ; --i) {
	invfac[i] = mul(invfac[i + 1],i + 1);
    }
    for(int i = 1 ; i <= N ; ++i) {
	read(p[i]);
	if(p[i]) vis[p[i]] = 1;
	else ++k;
    }
    int sum = 0;
    for(int i = N ; i >= 1 ; --i) {
	s[i] += s[i + 1];
	if(!vis[i]) {
	    s[i]++;
	    update(sum,i - 1);
	}
    }

    int pre = 0;
    int rem = 0;
    for(int i = 1 ; i <= N ; ++i) {
	if(!p[i]) {
	    update(ans[i],MOD - pre);
	    if(k >= 2) update(ans[i],MOD - mul(rem,mul(C(k,2),fac[k - 2])));
	    update(ans[i],mul(sum,fac[k - 1]));
	    ++rem;
	}
	else {
	    update(ans[i],mul(p[i] - 1,fac[k]));
	    update(ans[i],MOD - mul(query(p[i] - 1),fac[k]));
	    if(k) update(ans[i],MOD - mul(rem,mul(s[1] - s[p[i]],fac[k - 1])));
	    if(k) update(pre,mul(s[p[i] + 1],fac[k - 1]));
	    insert(p[i],1);
	}
    }
    int res = fac[k];
    for(int i = 1 ; i <= N ; ++i) {
	update(res,mul(fac[N - i],ans[i]));
    }
    out(res);enter;
}

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