2021牛客寒假算法基础集训营2

  菜鸡自闭场  

H. 牛牛与棋盘

签到成功

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const double PI = acos(-1.0);
const ll N = 8e7 + 7;
const ll inf = 0x3f3f3f3f;
const ll mod = 1e9 + 7;

int main() {
    int n;
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i) {
        for(int j = 1; j <= n; ++j) {
            if(i & 1) {
                if(j & 1) printf("0");
                else printf("1");
            }
            else {
                if(j & 1) printf("1");
                else printf("0");
            }
        }
        printf("\n");
    }
	return 0;
}

F.牛牛与交换排序

 emm栈模拟的,将有序的开头和结尾去掉,如(1 2 3) 6 5 4 (7 8 9),只处理中间区间,发现下一个数应该是4,4必须一次性反转到3后面,所以k就应该是3。知道k了之后模拟就可以了,每轮连续扔进栈里k个数,从栈顶开始pop,看pop出来的数字是不是对应顺序的数,如果不是就停止pop,把栈反转(用deque比较方便,赛时用vector的reverse模拟栈反转的),接着下一轮push。最后如果栈空说明可以按顺序(1, 2, 3, ..., n)构成排列,就是yes,否则no.

注意在新一轮push开始时,如果栈空并且当前的a[i]正好是要找的数,就直接跳过,不要push,如1 2 5 4 3 6 9 8 7 10里的6,应该直接跳过。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int N = 1e5 + 10;

int a[N];

int main() {
    int n;
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
    int be = n + 1, ed = 0;
    for(int i = 1; i <= n; ++i) {
        if(a[i] != i) {
            be = i;
            break;
        }
    }
    for(int i = n; i >= 1; --i) {
        if(a[i] != i) {
            ed = i;
            break;
        }
    }
    int k = 0;
    for(int i = be + 1; i <= ed; ++i) {
        if(a[i] == be) {
            k = i - be + 1;
            break;
        }
    }
    if(!k) {
        printf("yes\n%d\n", 1);
        return 0;
    }
    vector<int>st;
    for(int i = be; i <= ed; ++i) {
        if(st.empty() && a[i] == be) {
            be++;
            continue;
        }
        if(st.size() < k) st.emplace_back(a[i]);
        if(st.size() == k) {
            while(!st.empty() && st.back() == be) st.pop_back(), be++;
            reverse(st.begin(), st.end());
        }
    }
    if(!st.empty()) printf("no\n");
    else printf("yes\n%d\n", k);
    return 0;
}
/*
7
1 6 3 2 5 4 7
8
1 4 7 2 3 6 5 8
10
1 2 5 4 3 6 9 8 7 10
*/

I.牛牛的“质因数”

一下午卡死在这个题上,一定要长记性

赛时写了几遍模拟,T飞也是意料之中的事情,就是不知道那里还能优化,后来看了大佬的代码意识到,一个数x的答案可以从 x / pri 转移过来,pri 是 x 的最小质因子,所以在线性筛记录每个数的最小质因子,就可以线性实现质因子分解,剩下的活模拟即可。

暂时补了两种写法,一种按数字位数乘基数累加,另一种无脑string模拟,dp稍后补

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const double PI = acos(-1.0);
const int inf = 0x3f3f3f3f;
const ll mod = 1e9 + 7;
const int N = 4e6 + 7;

ll ans, base[105];
int pri[N], tot, fac[N], n, lg[N];
bool vis[N];

void init() {
    base[0] = 1;
    for(int i = 1; i < 105; ++i) base[i] = base[i - 1] * 10 % mod;
    for(int i = 1; i < N; ++i) lg[i] = lg[i / 10] + 1;
    tot = 0;
    for(int i = 2; i < N; ++i) {
        if(!vis[i]) {
            pri[++tot] = i;
            fac[i] = i;
        }
        for(int j = 1; j <= tot && i * pri[j] < N; ++j) {
            vis[i * pri[j]] = 1;
            fac[i * pri[j]] = pri[j];
            if(i % pri[j] == 0) break;
        }
    }
}

void solve() {
    for(int i = 2; i <= n; ++i) {
        ll res = 0;
        int tmp = i;
        while(tmp > 1) {
            res = (res * base[lg[fac[tmp]]] % mod + fac[tmp]) % mod;
            tmp /= fac[tmp];
        }
        ans = (ans + res) % mod;
    }
}

int main() {
    init();
    scanf("%d", &n);
    ans = 0, solve();
    printf("%lld\n", ans);
	return 0;
}
//string模拟 不推荐
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const double PI = acos(-1.0);
const int N = 4e6 + 7;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;

ll ans;
int pri[N], tot, fa[N], fa_pri[N], n;
bool vis[N];
string str[N];

string tostring(int x) {
    string s = "";
    while(x) {
        s = char(x % 10 + '0') + s;
        x /= 10;
    }
    return s;
}

ll tonumber(string s) {
    ll res = 0, base = 1;
    int siz = s.size();
    for(int i = siz - 1; i >= 0; --i) {
        res = (res + base * (s[i] - '0') % mod) % mod;
        base = base * 10 % mod;
    }
    return res;
}

void prime() {
    tot = 0;
    for(int i = 2; i <= n; ++i) {
        if(!vis[i]) {
            pri[++tot] = i;
            fa[i] = 1;
            fa_pri[i] = i;
        }
        for(int j = 1; j <= tot; ++j) {
            if(i * pri[j] > n) break;
            vis[i * pri[j]] = 1;
            fa[i * pri[j]] = i;
            fa_pri[i * pri[j]] = pri[j];
            if(i % pri[j] == 0) break;
        }
    }
}

void solve() {
    for(int i = 2; i <= n; ++i) {
        str[i] = "";
        int tmp = i;
        while(tmp > 1) {
            str[i] += tostring(fa_pri[tmp]);
            tmp = fa[tmp];
            if(str[tmp] != "") {
                str[i] += str[tmp];
                break;
            }
        }
        ans = (ans + tonumber(str[i])) % mod;
    }
}

int main() {
    scanf("%d", &n);
    prime();
    ans = 0, solve();
    printf("%lld\n", ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43871207/article/details/113642419