【AtCoder】AGC003

AGC編號越小越水????c++

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('\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);
}
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

先把每一個卡本身都配對,取模2spa

而後剩餘的單張卡若是距離下一張單張卡之間的卡都有對子,那麼拆掉這些對子能夠得到加1的貢獻,掃一遍就行了code

#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],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!

由於三個交換不改變每一個數所在位置的奇偶性,若是一個數的目標位置和本身所在位置的奇偶性不一樣那麼就須要一次Op1ci

計算全部當前位置和目標位置奇偶性不一樣的位置除二便可get

#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 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}}\)給全部的數的質數指數冪取模3string

初始答案設成N,統計1的個數是cnt,若cnt不爲0,答案減掉cnt - 1it

而後分析一下,每一個數只有惟一的一個各個質數指數不超過3的數和這個數配對使得這個數成爲立方數io

如何找這個數呢,質因數分解顯然會超時class

可是分析一下,若是隻有一個質數的話,咱們特判掉,而後咱們默認用配對的數中的小的和大的配,這樣的話質數最大的範圍能夠這麼考慮

若是這個數是\(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('\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;
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('\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,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('\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 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;
}
相關文章
相關標籤/搜索