zoukankan      html  css  js  c++  java
  • Atcoder Grand Contest 003 题解

    A - Wanna go back home

    如果有S就必须要有N,反之亦然,如果有E必须要有W,反之亦然。判断一下就好了。

    //waz
    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define ALL(x) (x).begin(), (x).end()
    #define SZ(x) ((int)((x).size()))
    
    typedef pair<int, int> PII;
    typedef vector<int> VI;
    typedef long long int64;
    typedef unsigned int uint;
    typedef unsigned long long uint64;
    
    #define gi(x) ((x) = F())
    #define gii(x, y) (gi(x), gi(y))
    #define giii(x, y, z) (gii(x, y), gi(z))
    
    int F()
    {
    	char ch;
    	int x, a;
    	while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-');
    	if (ch == '-') ch = getchar(), a = -1;
    	else a = 1;
    	x = ch - '0';
    	while (ch = getchar(), ch >= '0' && ch <= '9')
    		x = (x << 1) + (x << 3) + ch - '0';
    	return a * x;
    }
    
    int n;
    char str[2333];
    bool t[4];
    
    int main()
    {
    	scanf("%s", str + 1); n = strlen(str + 1);
    	for (int i = 1; i <= n; ++i)
    	{
    		if (str[i] == 'W') t[0] = 1;
    		if (str[i] == 'E') t[1] = 1;
    		if (str[i] == 'N') t[2] = 1;
    		if (str[i] == 'S') t[3] = 1;
    	}
    	puts(t[0] == t[1] && t[2] == t[3] ? "Yes" : "No");
    }
    

      

    B - Simplified mahjong

    先O(n)扫一遍,把奇数的能删就删去一个。最后每个除以二再求和就好了。

    //waz
    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define ALL(x) (x).begin(), (x).end()
    #define SZ(x) ((int)((x).size()))
    
    typedef pair<int, int> PII;
    typedef vector<int> VI;
    typedef long long int64;
    typedef unsigned int uint;
    typedef unsigned long long uint64;
    
    #define gi(x) ((x) = F())
    #define gii(x, y) (gi(x), gi(y))
    #define giii(x, y, z) (gii(x, y), gi(z))
    
    int F()
    {
    	char ch;
    	int x, a;
    	while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-');
    	if (ch == '-') ch = getchar(), a = -1;
    	else a = 1;
    	x = ch - '0';
    	while (ch = getchar(), ch >= '0' && ch <= '9')
    		x = (x << 1) + (x << 3) + ch - '0';
    	return a * x;
    }
    
    int n, a[100010];
    
    long long ans;
    
    int main()
    {
    	gi(n);
    	for (int i = 1; i <= n; ++i) gi(a[i]);
    	for (int i = 1; i <= n; ++i)
    	{
    		if (a[i] & 1)
    		{
    			if (a[i + 1]) ++ans, --a[i], --a[i + 1];
    		}
    	}
    	for (int i = 1; i <= n; ++i)
    	{
    		ans += a[i] >> 1;
    	}
    	printf("%lld
    ", ans);
    	return 0;
    }
    

      

    C - BBuBBBlesort!

     我们发现操作2使得奇数偶数独立,我们只要算应该在奇数位置最后到偶数位置的数有多少个就好了。

    //waz
    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define ALL(x) (x).begin(), (x).end()
    #define SZ(x) ((int)((x).size()))
    
    typedef pair<int, int> PII;
    typedef vector<int> VI;
    typedef long long int64;
    typedef unsigned int uint;
    typedef unsigned long long uint64;
    
    #define gi(x) ((x) = F())
    #define gii(x, y) (gi(x), gi(y))
    #define giii(x, y, z) (gii(x, y), gi(z))
    
    int F()
    {
    	char ch;
    	int x, a;
    	while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-');
    	if (ch == '-') ch = getchar(), a = -1;
    	else a = 1;
    	x = ch - '0';
    	while (ch = getchar(), ch >= '0' && ch <= '9')
    		x = (x << 1) + (x << 3) + ch - '0';
    	return a * x;
    }
    
    int n;
    
    PII a[100010];
    
    int main()
    {
    	gi(n);
    	for (int i = 1; i <= n; ++i) gi(a[i].fi), a[i].se = i;
    	sort(a + 1, a + n + 1);
    	int ans = 0;
    	for (int i = 1; i <= n; ++i) if ((a[i].se & 1) != (i & 1)) ++ans;
    	printf("%d
    ", ans >> 1);
    	return 0;
    }
    

      

    D - Anticube

    首先因子里有立方的可以直接除掉,不会有影响,那么一个数对应的就是唯一的,筛法找出那个数字,算一下就好了。

    //waz
    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define ALL(x) (x).begin(), (x).end()
    #define SZ(x) ((int)((x).size()))
    
    typedef pair<int, int> PII;
    typedef vector<int> VI;
    typedef long long int64;
    typedef unsigned int uint;
    typedef unsigned long long uint64;
    
    #define gi(x) ((x) = F())
    #define gii(x, y) (gi(x), gi(y))
    #define giii(x, y, z) (gii(x, y), gi(z))
    
    int F()
    {
    	char ch;
    	int x, a;
    	while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-');
    	if (ch == '-') ch = getchar(), a = -1;
    	else a = 1;
    	x = ch - '0';
    	while (ch = getchar(), ch >= '0' && ch <= '9')
    		x = (x << 1) + (x << 3) + ch - '0';
    	return a * x;
    }
    
    int n;
    
    long long s[100010];
    
    map<long long, int> h, t;
    
    int p[3010], fg[3010], pt;
    
    int main()
    {
    	gi(n);
    	for (int i = 1; i <= n; ++i) scanf("%lld", s + i);
    	for (int i = 2; i <= 3000; fg[i] ? : p[++pt] = i, ++i)
    		for (int j = i << 1; j <= 3000; j += i)
    			fg[j] = 1;
    	long long mx = 0;
    	for (int i = 1; i <= n; ++i)
    	{
    		for (int j = 1; 1LL * p[j] * p[j] * p[j] <= s[i]; ++j)
    		{
    			long long t = 1LL * p[j] * p[j] * p[j];
    			while (!(s[i] % t)) s[i] /= t;
    		}
    		++h[s[i]];
    		mx = max(mx, s[i]);
    		//cerr << "s = " << s[i] << endl;
    	}
    	int ans = 0;
    	t = h;
    	for (auto iter : t)
    	{
    		long long x = iter.first;
    		if (x == 1) continue;
    		long long y = 1;
    		for (int j = 1; j <= pt; ++j)
    		{
    			int cnt = 0;
    			while (!(x % p[j])) x /= p[j], ++cnt;
    			if (cnt == 1) y *= p[j] * p[j];
    			else if (cnt == 2) y *= p[j];
    		}
    		if (x != 1)
    		{
    			long long s = sqrt(x);
    			if (x == s * s)
    				y *= s;
    			else 
    				y *= x * x;
    		}
    		//cerr << iter.first << ", " << y << ", " << x << endl;
    		if(!h.count(y) || iter.first < y) ans += max(iter.second, h.count(y) ? h[y] : 0);
    	}
    	if (h[1]) ++ans;
    	printf("%d
    ", ans);
    	return 0;
    }
    

      

    E - Sequential operations on Sequence

    倒着模拟,首先qi变成单调上升的,就可以二分了。

    //waz
    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define ALL(x) (x).begin(), (x).end()
    #define SZ(x) ((int)((x).size()))
    
    typedef pair<int, int> PII;
    typedef vector<int> VI;
    typedef long long int64;
    typedef unsigned int uint;
    typedef unsigned long long uint64;
    
    #define gi(x) ((x) = F())
    #define gii(x, y) (gi(x), gi(y))
    #define giii(x, y, z) (gii(x, y), gi(z))
    
    int F()
    {
    	char ch;
    	int x, a;
    	while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-');
    	if (ch == '-') ch = getchar(), a = -1;
    	else a = 1;
    	x = ch - '0';
    	while (ch = getchar(), ch >= '0' && ch <= '9')
    		x = (x << 1) + (x << 3) + ch - '0';
    	return a * x;
    }
    
    const int N = 1e5 + 10;
    
    int n, Q, m;
    
    long long q[N], t[N], s[N];
    
    int find(long long k, int n)
    {
    	int t = 0;
    	for (int i = 19; ~i; --i)
    	{
    		if (t + (1 << i) > n) continue;
    		if (q[t + (1 << i)] <= k) t += 1 << i;
    	}
    	return t;
    }
    
    int main()
    {
    	gii(n, Q);
    	q[++m] = n;
    	for (int i = 1; i <= Q; ++i)
    	{
    		long long x;
    		scanf("%lld", &x);
    		while (x <= q[m]) --m;
    		q[++m] = x;
    	}
    	t[m] = 1;
    	for (int i = m; i; --i)
    	{
    		long long k = q[i];
    		int p = find(k, i - 1);
    		while (p)
    		{
    			t[p] += (k / q[p]) * t[i];
    			k %= q[p];
    			p = find(k, p - 1);
    		}
    		s[1] += t[i], s[k + 1] -= t[i];
    	}
    	long long ans = 0;
    	for (int i = 1; i <= n; ++i) ans += s[i], printf("%lld
    ", ans);
    	return 0;
    }
    

      

    F - Fraction of Fractal

    首先考虑行有连接列也有连接的,那么连通块个数肯定为1,都没有连接就是黑格子个数的K-1次方,只有一边连接,假设是行,从K拓展到K+1的时候,公式:K+1层的连通块个数=K层的黑格子个数-K层的左右格子对,因为上下不会扩展,所以只要减去左右,那么我们就要维护黑格子个数和左右相连的格子有多少个,还要再维护边界有多少相邻,才能转移。

    x' = x^2(黑格子个数)

    y' = z * y + x * y(左右相连格子个数)

    z' = z * z(边界相邻格子数)

    矩阵乘法计算就好了。

    //waz
    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define ALL(x) (x).begin(), (x).end()
    #define SZ(x) ((int)((x).size()))
    
    typedef pair<int, int> PII;
    typedef vector<int> VI;
    typedef long long int64;
    typedef unsigned int uint;
    typedef unsigned long long uint64;
    
    #define gi(x) ((x) = F())
    #define gii(x, y) (gi(x), gi(y))
    #define giii(x, y, z) (gii(x, y), gi(z))
    
    int F()
    {
    	char ch;
    	int x, a;
    	while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-');
    	if (ch == '-') ch = getchar(), a = -1;
    	else a = 1;
    	x = ch - '0';
    	while (ch = getchar(), ch >= '0' && ch <= '9')
    		x = (x << 1) + (x << 3) + ch - '0';
    	return a * x;
    }
    
    const int mod = 1e9 + 7;
    
    struct matrix
    {
    	int a[2][2];
    	matrix operator * (matrix that) 
    	{
    		matrix ans;
    		memset(ans.a, 0, sizeof ans.a);
    		for (int i = 0; i < 2; ++i)
    			for (int j = 0; j < 2; ++j)
    				for (int k = 0; k < 2; ++k)
    					ans.a[i][j] = (ans.a[i][j] + 1LL * a[i][k] * that.a[k][j]) % mod;
    		return ans;
    	}
    } w;
    
    int fpow(int a, long long x)
    {
    	int ret = 1;
    	for (; x; x >>= 1)
    	{
    		if (x & 1) ret = 1LL * ret * a % mod;
    		a = 1LL * a * a % mod;
    	}
    	return ret;
    }
    
    matrix fpow(matrix a, long long x)
    {
    	matrix ret;
    	memset(ret.a, 0, sizeof ret.a);
    	ret.a[0][0] = ret.a[1][1] = 1;
    	for (; x; x >>= 1)
    	{
    		if (x & 1) ret = ret * a;
    		a = a * a;
    	}
    	return ret;
    }
    
    int H, W;
    
    long long K;
    
    char str[1010][1010];
    
    int main()
    {
    	scanf("%d%d%lld", &H, &W, &K);
    	for (int i = 1; i <= H; ++i)
    		scanf("%s", str[i] + 1);
    	int cntH = 0, cntW = 0;
    	for (int i = 1; i <= H; ++i)
    		if (str[i][1] == str[i][W] && str[i][1] == '#') ++cntH;
    	for (int i = 1; i <= W; ++i)
    		if (str[1][i] == str[H][i] && str[1][i] == '#') ++cntW;
    	int cnt = 0;
    	for (int i = 1; i <= H; ++i)
    		for (int j = 1; j <= W; ++j)
    			if (str[i][j] == '#') ++cnt;
    	if (!cntH && !cntW)
    	{
    		printf("%d
    ", fpow(cnt, K - 1));
    		return 0;
    	}
    	if ((cntH && cntW) || !K)
    	{
    		puts("1");
    		return 0;
    	}
    	if (cntH)
    	{
    		w.a[0][0] = cnt;
    		for (int i = 1; i <= H; ++i)
    			for (int j = 1; j < W; ++j)
    				if (str[i][j] == '#' && str[i][j + 1] == '#')
    					++w.a[0][1];
    		w.a[1][1] = cntH;
    	}
    	else
    	{
    		w.a[0][0] = cnt;
    		for (int i = 1; i < H; ++i)
    			for (int j = 1; j <= W; ++j)
    				if (str[i][j] == '#' && str[i + 1][j] == '#')
    					++w.a[0][1];
    		w.a[1][1] = cntW;
    	}
    	w = fpow(w, K - 1);
    	printf("%d
    ", (w.a[0][0] - w.a[0][1] + mod) % mod);
    	return 0;
    }
    

      

  • 相关阅读:
    BZOJ 2152 聪聪可可
    hdu 1028 && hdu 1398 && hdu 1085 && hdu 1171 ——生成函数
    bzoj 4827 [Hnoi2017]礼物——FFT
    bzoj 4503 两个串——FFT
    bzoj 3527 [Zjoi2014]力——FFT
    bzoj 3160 万径人踪灭——FFT
    bzoj 2194 快速傅立叶之二
    bzoj 2179 FFT快速傅立叶
    洛谷 3803 【模板】多项式乘法(FFT)
    CF 622F The Sum of the k-th Powers——拉格朗日插值
  • 原文地址:https://www.cnblogs.com/AnzheWang/p/9609705.html
Copyright © 2011-2022 走看看