菜鸡自闭场
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;
}