【AtCoder】AGC003

AGC编号越小越水????

AGC003

A - Wanna go back home

相对方向要么一起有要么一起没有

#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('
')
#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);
}
string s;
map<char,int> zz;
void Solve() {
    cin >> s;
    for(int i = 0 ; i < s.length() ; ++i) zz[s[i]] = 1;
    if((zz['W'] ^ zz['E']) & 1) {puts("No");return;}
    if((zz['N'] ^ zz['S']) & 1) {puts("No");return;}
    puts("Yes");
}

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

B - Simplified mahjong

先把每个卡自己都配对,取模2

然后剩余的单张卡如果距离下一张单张卡之间的卡都有对子,那么拆掉这些对子可以获得加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('
')
#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],pa[MAXN];
int64 ans = 0;
void Solve() {
    read(N);
    for(int i = 1 ; i <= N ; ++i) {
	read(A[i]);
	ans += A[i] / 2;
	pa[i] = A[i] / 2;
	A[i] %= 2;
    }
    int pre = -1;
    for(int i = 1 ; i <= N ; ++i) {
	if(A[i]) {
	    if(pre == -1) pre = i;
	    else {pre = -1;++ans;}
	}
	else {
	    if(!pa[i]) pre = -1;
	}
    }
    out(ans);enter;
}

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

C - BBuBBBlesort!

因为三个交换不改变每个数所在位置的奇偶性,如果一个数的目标位置和自己所在位置的奇偶性不同那么就需要一次Op1

计算所有当前位置和目标位置奇偶性不同的位置除二即可

#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('
')
#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 cnt[2],A[MAXN],N,B[MAXN];
map<int,int> zz;
void Solve() {
    read(N);
    for(int i = 1 ; i <= N ; ++i) {read(A[i]);B[i] = A[i];}
    sort(B + 1,B + N + 1);
    for(int i = 1 ; i <= N ; ++i) zz[B[i]] = i;
    for(int i = 1 ; i <= N ; ++i) {
	if(((zz[A[i]] ^ i) & 1) != 0) cnt[i & 1]++;
    }
    out(cnt[0]);enter;
}

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

D - Anticube

先用(sqrt[3]{10^{10}})给所有的数的质数指数幂取模3

初始答案设成N,统计1的个数是cnt,若cnt不为0,答案减掉cnt - 1

然后分析一下,每个数只有唯一的一个各个质数指数不超过3的数和这个数配对使得这个数成为立方数

如何找这个数呢,质因数分解显然会超时

但是分析一下,如果只有一个质数的话,我们特判掉,然后我们默认用配对的数中的小的和大的配,这样的话质数最大的范围可以这么考虑

如果这个数是(pq)的话,(p,q)都是质数,和它配对的是(p^{2}q^{2}),这个数也要在(10^{10})的范围内,所以至多只有一个数大于(sqrt[4]{10^{10}})

如果这个数是(p^2q),配对的是(pq^{2}),那么至多只有一个数大于(sqrt[3]{10^{10}})

且最大的那个质数不大于(10^{5})

所以我们预处理出(10^5)以内每个数是不是质数用来判断,质数分解的时候只需要用(sqrt[3]{10^{10}})以内的

这样大概不到1s就过了

#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('
')
#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;
int64 S[MAXN],pre[1000005];
int prime[MAXN],tot,cnt;
bool nonprime[MAXN];
map<int64,int> zz;
int s[7] = {4,7,11,29,47,71,87};
vector<int64> v;
int64 mul(int64 a,int64 b,int64 MOD) {
    int64 res = 0,t = a;
    while(b) {
	if(b & 1) res = (res + t) % MOD;
	t = (t + t) % MOD;
	b >>= 1;
    }
    return res;
}
int64 fpow(int64 a,int64 c,int64 MOD) {
    int64 res = 1,t = a;
    while(c) {
	if(c & 1) res = mul(res,t,MOD);
	t = mul(t,t,MOD);
	c >>= 1;
    }
    return res;
}
bool check(int64 s,int t,int64 MOD) {
    if(s == 1) return true;
    for(int i = 1 ; i <= t ; ++i) {
	int64 nxt = mul(s,s,MOD);
	if(nxt == 1) {
	    if(s == MOD - 1) return true;
	    return false;
	}
    }
    return false;
}
bool miller_rabin(int64 x) {
    int t = 0;int64 tmp = x - 1;
    while(tmp % 2 == 0) {++t;tmp /= 2;}
    for(int i = 0 ; i < 7 ; ++i) {
	if(!check(fpow(s[i],tmp,x),t,x)) return false;
    }
    return true;
}
void Solve() {
    read(N);
    for(int64 i = 1 ; i <= 1000000 ; ++i) pre[i] = i * i * i;
    for(int64 i = 2 ; i <= 100000 ; ++i) {
	if(!nonprime[i]) {
	    prime[++tot] = i;
	}
	for(int j = 1 ; j <= tot ; ++j) {
	    if(i * prime[j] > 100000) break;
	    nonprime[i * prime[j]] = 1;
	    if(i % prime[j] == 0) break;
	}
    }
    int ans = N;
    for(int i = 1 ; i <= N ; ++i) {
	read(S[i]);
	for(int j = 1 ; j <= 500 ; ++j) {
	    if(pre[prime[j]] > S[i]) break;
	    while(S[i] % pre[prime[j]] == 0) S[i] /= pre[prime[j]];
	}
	if(S[i] == 1) ++cnt;
	else {zz[S[i]]++;v.pb(S[i]);}
    }
    sort(v.begin(),v.end());
    v.erase(unique(v.begin(),v.end()),v.end());
    if(cnt > 1) ans -= (cnt - 1);
    for(auto num : v) {
	int64 t = sqrt(num);
	if(t * t == num) continue;
	if(num <= 100000 && !nonprime[num]) {ans -= min(zz[num],zz[num * num]);}
	else {
	    int64 x = num;
	    int64 op = 1;
	    for(int i = 1 ; i <= 500 ; ++i) {
		if(prime[i] > 3500 || prime[i] > x) break;
		if(x % prime[i] == 0) {
		    int c = 0;
		    while(x % prime[i] == 0) {x /= prime[i];++c;}
		    c = 3 - c;
		    op = op * prime[i];
		    if(op > 1e10) goto fail;
		    if(c == 2) op = op * prime[i];
		    if(op > 1e10) goto fail;
		}
	    }
	    if(x != 1) {
		if(x <= 100000) {
		    if(nonprime[x]) goto fail;
		    for(int i = 0 ; i < 2 ; ++i) {
			op = op * x;
			if(op > 1e10) goto fail;
		    }
		}
		else {
		    goto fail;
		}
	    }
	    
	    if(op > num) ans -= min(zz[num],zz[op]);
	}
        fail:;
    }
    out(ans);enter;
}

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

E - Sequential operations on Sequence

用一个单调栈,每次来一个操作弹出到第一个小于它的,然后我们得到一个新的操作序列这个和原来的操作序列结果是一样的

这个时候我们每次操作都是递增的,第一个大小是a的话,那么第一个序列就是1,2,3,4...a

然后我们把栈顶的统计次数设为1,sta[i - 1]的统计次数要加上是(sta[i] / sta[i - 1] * cnt[i])

然后我们有一个余数是(sta[i] \% sta[i - 1])

我们二分找到第一个小于这个余数的序列,计算余数除这个序列的次数乘上本序列统计次数加到这个序列上,然后余数取模序列长度,直到余数小于等于一个序列大小,此时若为b,ans[b] += cnt[i],之后统计一个后缀和就是答案

因为每次取模余数都会减少一半,所以复杂度是$Q log{max{ q{i}}} log N $

#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('
')
#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,Q,top;
int64 sta[MAXN];
int64 cnt[MAXN],ans[MAXN];
void Solve() {
    read(N);read(Q);
    sta[++top] = N;
    int64 p;
    for(int i = 1 ; i <= Q ; ++i) {
	read(p);
	while(top && sta[top] >= p) --top;
	sta[++top] = p;
    }
    cnt[top] = 1;
    for(int i = top ; i >= 1 ; --i) {
	if(i != top) cnt[i] += cnt[i + 1] * (sta[i + 1] / sta[i]);
	if(i == 1) {ans[sta[1]] += cnt[1];continue;}
	int64 r = sta[i] % sta[i - 1];
	while(r > sta[1]) {
	    int t = upper_bound(sta + 1,sta + top + 1,r) - sta - 1;
	    cnt[t] += cnt[i] * (r / sta[t]);
	    r %= sta[t];
	}
	ans[r] += cnt[i];
    }
    for(int i = N ; i >= 1 ; --i) ans[i] += ans[i + 1];
    for(int i = 1 ; i <= N ; ++i) {
	out(ans[i]);enter;
    }
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Solve();mahjong
    return 0;
}

F - Fraction of Fractal

简单分析一下,如果初始图形复制一份左右拼接不上,上下拼接不上,那就是黑色个数的(K - 1)次方

如果左右拼上,上下拼上,那就是1

如果只有左右拼上,初始认为每一个黑格子都会新形成一个联通块,那么新来一个右边会减少1,此时如果左右拼上的行很多,那么过了一个level之后,这些行也会相连接导致联通块减少

所以对于每个方块统计它右边有没有方块,记为h,以及能起始和终止都有黑格子的行有几个,记为a,总联通块个数记为b

那么(f(k + 1) = bf(k) - h * a^{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('
')
#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 H,W,all,h,c;
int64 K;
char s[1005][1005];
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);
}
struct Matrix {
    int f[2][2];
    Matrix() {memset(f,0,sizeof(f));}
    friend Matrix operator * (const Matrix &a,const Matrix &b) {
	Matrix c;
	for(int i = 0 ; i < 2 ; ++i) {
	    for(int j = 0 ; j < 2 ; ++j) {
		for(int k = 0 ; k < 2 ; ++k) {
		    update(c.f[i][j],mul(a.f[i][k],b.f[k][j])); 
		}
	    }
	}
	return c;
    }
}a,ans;
Matrix fpow(Matrix x,int64 c) {
    Matrix res,t = x;
    res.f[0][0] = res.f[1][1] = 1;
    while(c) {
	if(c & 1) res = res * t;
	t = t * t;
	c >>= 1;
    }
    return res;
}
int fpow(int x,int64 c) {
    int64 res = 1,t = x;
    while(c) {
	if(c & 1) res = mul(res,t);
	t = mul(t,t);
	c >>= 1;
    }
    return res;
}
void Solve() {
    read(H);read(W);read(K);
    if(K == 0 || K == 1) {puts("1");return;}
    for(int i = 1 ; i <= H ; ++i) scanf("%s",s[i] + 1);
    for(int i = 1 ; i <= H ; ++i) {
	for(int j = 1 ; j <= W ; ++j) {
	    if(s[i][j] == '#') {
		++all;
		if(s[i][j + 1] == '#') ++h;
		if(s[i + 1][j] == '#') ++c;
	    }
	}
    }
    bool f1 = 0;int c1 = 0;
    for(int i = 1 ; i <= H ; ++i) {
	if(s[i][1] == '#' && s[i][W] == '#') {f1 = 1;++c1;}
    }
    bool f2 = 0;int c2 = 0;
    for(int i = 1 ; i <= W ; ++i) {
	if(s[1][i] == '#' && s[H][i] == '#') {f2 = 1;++c2;}
    }
    if(f1 && f2) {puts("1");return;}
    if(!f1 && !f2) {
	out(fpow(all,K - 1));enter;return;
    }
    if(f1) {
	a.f[1][0] = MOD - h;
	a.f[1][1] = c1;
    }
    else if(f2) {
	a.f[1][0] = MOD - c;
	a.f[1][1] = c2;
    }
    a.f[0][0] = all;
    ans = fpow(a,K - 1);
    out(inc(ans.f[0][0],ans.f[1][0]));enter;
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Solve();
    return 0;
}
原文地址:https://www.cnblogs.com/ivorysi/p/10903767.html