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\n", 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\n", 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\n", 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\n", 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\n", 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\n", (w.a[0][0] - w.a[0][1] + mod) % mod);
return 0;
}