博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
牛客挑战赛32
阅读量:4656 次
发布时间:2019-06-09

本文共 6205 字,大约阅读时间需要 20 分钟。

sol
真的有人不会做这道题?
#include
using namespace std; int main(){ string s; int N; cin >> N; for(int i = 1 ; i <= N ; ++i){ cin >> s; if(s.size() >= 2 && s[s.size() - 1] == 'K' && s[s.size() - 2] == 'A'){ for(int i = 0 ; i < s.size() - 2 ; ++i) cout << s[i]; return 0; } } return 0;}

sol $114514$只有$8$个约数,暴力统计数量然后人脑枚举所有可行方案就行了。
#include
using namespace std; #define int unsigned long longconst int _ = 229029 , tar[] = {2,31,1847};signed main(){ int N; cin >> N; static int arr[_] , num[8]; for(int i = 1 ; i <= N ; ++i){ cin >> arr[i]; if(arr[i] != 0) if(114514 % arr[i] == 0){ int cur = 0; for(int j = 0 ; j < 3 ; ++j) if(arr[i] % tar[j] == 0) cur |= 1 << j; ++num[cur]; } } int p = num[7] + num[6] * num[1] + num[5] * num[2] + num[3] * num[4] + num[1] * num[2] * num[4]; cout << p * (1 + num[0]); return 0;}

sol 把前几项算出来丢到OEIS里发现递推公式:$a_i=2a_{i-1}+a_{i-2}-2a_{i-3}-a_{i-4}$,然后矩乘就行了。
#include
using namespace std; #define int long longconst int MOD = 998244353;struct matrix{ int a[4][4]; matrix(){memset(a , 0 , sizeof(a));} int* operator [](int x){return a[x];} matrix operator *(matrix b){ matrix c; for(int i = 0 ; i < 4 ; ++i) for(int k = 0 ; k < 4 ; ++k) for(int j = 0 ; j < 4 ; ++j) c[i][j] = (c[i][j] + a[i][k] * 1ll * b[k][j]) % MOD; return c; }}G , T; signed main(){ int N; cin >> N; if(N == 1) puts("0"); else if(N == 2) puts("1"); else if(N == 3) puts("2"); else if(N == 4) puts("5"); else{ T[1][0] = T[2][1] = T[3][2] = 1; T[3][3] = 2; T[2][3] = 1; T[1][3] = MOD - 2; T[0][3] = MOD - 1; N -= 4; G[0][0] = 0; G[0][1] = 1; G[0][2] = 2; G[0][3] = 5; while(N){ if(N & 1) G = G * T; T = T * T; N >>= 1; } cout << G[0][3]; } return 0;}

sol 考虑枚举$1 \leq i$
枚举$i,j$放在了$p_i,p_j$中多少个位置:
如果放了两个位置,一定是$j$在$p_i$、$i$在$p_j$。如果这样会产生贡献,那么我们就用$|i-j||p_i-p_j|p(N-2,N-2)$贡献答案;
如果放了一个位置,考虑$j$在$p_i$、$i$在$p_j$两种情况的可行方案距离总和,有可能会出现$i$在$p_j$、$j$在$p_i$的情况减掉,得到可行方案距离总和$S$。我们就可以用$|i-j|Sp(N-2,N-3)$贡献答案。
如果一个位置都没有,就是总距离$\sum\limits_{i=1}^{N-1}S_i$减去上述两种方案的距离乘上$|i-j|$乘上$p(N-2,N-4)$贡献答案。
所以我们要算$p(N-2,N-2),p(N-2,N-3),p(N-2,N-4)$,直接容斥就行了。
#include
using namespace std; const int MOD = 998244353;int num[1003][3] , N , T , p[1003] , jc[1003] , inv[1003] , sum1[1003] , sum2[1003]; int poww(long long a , int b){ int times = 1; while(b){ if(b & 1) times = times * a % MOD; a = a * a % MOD; b >>= 1; } return times;} int ch(int a , int b){return 1ll * jc[a] * inv[b] % MOD * inv[a - b] % MOD;} int main(){ jc[0] = 1; for(int i = 1 ; i <= 1000 ; ++i) jc[i] = 1ll * jc[i - 1] * i % MOD; inv[1000] = poww(jc[1000] , MOD - 2); for(int i = 999 ; i >= 0 ; --i) inv[i] = inv[i + 1] * (i + 1ll) % MOD; for(int i = 1 ; i <= 1000 ; ++i) for(int j = 0 ; j <= i && j <= 2 ; ++j){ num[i][j] = 0; for(int k = 0 ; k <= i - j ; ++k) num[i][j] = (num[i][j] + (k & 1 ? MOD - 1ll : 1ll) * jc[i - k] % MOD * ch(i - j , k)) % MOD; } for(int i = 1 ; i <= 1000 ; ++i) sum1[i] = sum1[i - 1] + i; for(int i = 1 ; i <= 1000 ; ++i) sum2[i] = (sum2[i - 1] + sum1[i]) % MOD; for(cin >> T ; T ; --T){ cin >> N; int sum = 0; for(int i = 1 ; i <= N ; ++i) cin >> p[i]; if(N == 1){puts("0"); continue;} if(N == 2){printf("%d\n" , p[1] == 1 ? 1 : 0); continue;} for(int i = 1 ; i <= N ; ++i){ for(int j = i + 1 ; j <= N ; ++j){ int val = 0; val = (val + 1ll * num[N - 2][2] * (sum2[N - 1] - (sum1[p[i] - 1] + sum1[N - p[i]]) - (sum1[p[j] - 1] + sum1[N - p[j]]) + abs(p[i] - p[j])) % MOD + MOD) % MOD; val = (val + 1ll * num[N - 2][1] * (sum1[N - p[i]] + sum1[p[j] - 1] - 2 * max(p[j] - p[i] , 0)) % MOD + MOD) % MOD; if(p[i] < p[j]) val = (val + 1ll * num[N - 2][0] * (p[j] - p[i])) % MOD; sum = (sum + 1ll * val * (j - i)) % MOD; } } cout << sum << endl; } return 0;}

sol 考虑每一个点取正和取负对逆序对数量造成的影响。不难发现某个点取负可以使其子树中所有权值绝对值比它小的和它产生逆序对,而大于它的则一定由这个更大的点取正或者负来确定;它取正可以使其祖先中所有权值绝对值比它小的和它产生逆序对。
所以每个点取正取负对逆序对数量的贡献是独立的,不受其他节点的影响。
把两个的贡献一个二维数点、一个dfs的时候维护祖先权值进行计算,然后bitset优化背包就可以算出是否合法。
#include
using namespace std; int read(){int a; scanf("%d" , &a); return a;} const int _ = 1e5 + 7;vector < int > ch[_]; int N , ts , val[_] , lsh[_] , sum[_] , add[_][2] , dfn[_] , sz[_] , ind[_];bitset < 30001 > now; namespace BIT{#define lowbit(x) ((x) & -(x)) int arr[_]; void add(int x , int n){while(x <= N){arr[x] += n; x += lowbit(x);}} int qry(int x){int sum = 0; while(x){sum += arr[x]; x -= lowbit(x);}return sum;}} void dfs(int x , int p){ ind[dfn[x] = ++ts] = x; sz[x] = 1; add[x][0] = BIT::qry(val[x]); BIT::add(val[x] , 1); for(auto t : ch[x]) if(!sz[t]){dfs(t , x); sz[x] += sz[t];} BIT::add(val[x] , -1);} #define PII pair < int , int >void calc(){ vector < PII > qry; for(int i = 1 ; i <= N ; ++i){qry.push_back(PII(dfn[i] - 1 , -i)); qry.push_back(PII(dfn[i] + sz[i] - 1 , i));} sort(qry.begin() , qry.end()); int pos = 0; for(auto t : qry){ while(pos < t.first) BIT::add(val[ind[++pos]] , 1); int flg = t.second < 0 ? -1 : 1 , id = abs(t.second); add[id][1] += flg * BIT::qry(val[id]); }} int main(){ N = read(); for(int i = 1 ; i <= N ; ++i) val[i] = lsh[i] = read(); sort(lsh + 1 , lsh + N + 1); for(int i = 1 ; i <= N ; ++i) val[i] = lower_bound(lsh + 1 , lsh + N + 1 , val[i]) - lsh; for(int i = 1 ; i < N ; ++i){ int p = read() , q = read(); ch[p].push_back(q); ch[q].push_back(p); } dfs(1 , 0); calc(); now[0] = 1; for(int i = 1 ; i <= N ; ++i){bitset < 30001 > p = now , q = now; p <<= add[i][0]; q <<= --add[i][1]; now = p | q;} for(int Q = read() ; Q ; --Q) puts(now[read()] ? "Orz" : "QAQ"); return 0;}

我怎么可能会这种题

转载于:https://www.cnblogs.com/Itst/p/11560233.html

你可能感兴趣的文章
jap _spring _maven
查看>>
IIS principle
查看>>
Oracle 如何对中文字段进行排序
查看>>
第七章 数组实验
查看>>
003_ElasticSearch详解与优化设计
查看>>
windows hosts
查看>>
PHP 初学之登录查询小case
查看>>
Spring 4 官方文档学习(十五)CORS支持
查看>>
react学习笔记1
查看>>
Dao层设计
查看>>
css各种姿势的水平居中
查看>>
MYSQL 测试常用语句使用技巧
查看>>
基础细节知识
查看>>
树状数组求区间最大值
查看>>
一个简单的PHP网站结构
查看>>
Redis 学习之简介及安装
查看>>
jsp简单的学习
查看>>
[LeetCode][JavaScript]Number of 1 Bits
查看>>
[LeetCode][JavaScript]Plus One
查看>>
C语言-06复杂数据类型-01数组
查看>>