Educational Codeforces Round 17

A. k-th divisor

水题,把所有因子找出来排序然后找第\(k\)大

view code
//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
typedef long long int LL; void solve(){
LL n, k;
cin >> n >> k;
vector<LL> fac1;
vector<LL> fac2;
for(int i = 1; 1ll * i * i <= n; i++){
if(n%i) continue;
fac1.push_back(i);
if(i!=n/i) fac2.push_back(n/i);
}
reverse(fac2.begin(),fac2.end());
for(LL x : fac2) fac1.push_back(x);
if(k>fac1.size()) cout << -1 << endl;
else cout << fac1[k-1] << endl;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("Local.in","r",stdin);
freopen("ans.out","w",stdout);
#endif
// int tt; for(scanf("%d",&tt); tt--; solve());
solve();
return 0;
}

B. USB vs. PS/2

显然先把两种独立的能配的尽量给配了,最后再去配都适配的

view code
//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
typedef long long int LL;
void solve(){
static int a, b, c;
vector<int> v1, v2;
____();
cin >> a >> b >> c;
int n; cin >> n;
for(int i = 1; i <= n; i++){
int x; string s;
cin >> x >> s;
if(s[0]=='U') v1.push_back(x);
else v2.push_back(x);
}
sort(v1.begin(),v1.end());
sort(v2.begin(),v2.end());
int ptr1 = 0, ptr2 = 0;
int cnt = 0;
LL ret = 0;
while(ptr1<v1.size() and a){
ret += v1[ptr1++];
a--;
cnt++;
}
while(ptr2<v2.size() and b){
ret += v2[ptr2++];
b--;
cnt++;
}
while(c){
if(ptr1==v1.size() and ptr2==v2.size()) break;
c--; cnt++;
if(ptr1==v1.size()) ret += v2[ptr2++];
else if(ptr2==v2.size()) ret += v1[ptr1++];
else if(v1[ptr1]<v2[ptr2]) ret += v1[ptr1++];
else ret += v2[ptr2++];
}
cout << cnt << ' ' << ret << endl;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("Local.in","r",stdin);
freopen("ans.out","w",stdout);
#endif
solve();
return 0;
}

C. Two strings

显然\(b\)串需要删掉中间的部分,也就是保留前缀和后缀

记一下\(b\)串前面能保留\(x\)个的情况下在\(a\)串中的最后匹配位置和\(a\)串后面还有\(x\)个位置的情况下最多能匹配\(b\)串的后缀长度

注意合并了之后串长不能超过\(a\)串或者\(b\)串的长度

view code
//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 1e5+8; char s1[MAXN], s2[MAXN];
int nxt[MAXN][26], n, m, pos[MAXN], rpos[MAXN];
void solve(){
cin >> s1+1 >> s2+1;
n = strlen(s1 + 1);
m = strlen(s2 + 1);
for(int i = 0; i < 26; i++) nxt[n][i] = MAXN;
for(int i = n - 1; i >= 0; i--){
for(int j = 0; j < 26; j++) nxt[i][j] = nxt[i+1][j];
nxt[i][s1[i+1]-'a'] = i + 1;
}
for(int i = 1; i <= n; i++) pos[i] = MAXN;
int ptr = 0, now = 1;
while(now <= m and nxt[ptr][s2[now]-'a']!=MAXN){
ptr = nxt[ptr][s2[now]-'a'];
pos[now] = ptr;
now++;
}
reverse(s1+1,s1+1+n);
reverse(s2+1,s2+1+m);
for(int i = 0; i < 26; i++) nxt[n][i] = MAXN;
for(int i = n - 1; i >= 0; i--){
for(int j = 0; j < 26; j++) nxt[i][j] = nxt[i+1][j];
nxt[i][s1[i+1]-'a'] = i + 1;
}
ptr = 0, now = 1;
while(now <= m and nxt[ptr][s2[now]-'a']!=MAXN){
ptr = nxt[ptr][s2[now]-'a'];
rpos[n-ptr+1] = now;
now++;
}
for(int i = n; i >= 0; i--) rpos[i] = max(rpos[i],rpos[i+1]);
int maxx = 0, ps = -1;
for(int i = 0; i <= m; i++){
if(pos[i]==MAXN) break;
if(i+rpos[pos[i]+1]>=maxx){
maxx = i + rpos[pos[i]+1];
ps = i;
}
}
if(maxx==0) cout << "-" << endl;
else{
string a, b;
int rmatch = rpos[pos[ps]+1];
b = string(s2+1,s2+1+rmatch);
reverse(s2+1,s2+1+m);
a = string(s2+1,s2+1+ps);
reverse(b.begin(),b.end());
if(maxx>=m){
if(maxx<=n) cout << s2 + 1 << endl;
else cout << string(s2+1,s2+1+n) << endl;
}
else{
if(maxx<=n) cout << a + b << endl;
else cout << a + string(b.begin()+b.size()+a.size()-maxx,b.end()) << endl;
}
}
}
int main(){
#ifndef ONLINE_JUDGE
freopen("Local.in","r",stdin);
freopen("ans.out","w",stdout);
#endif
// int tt; for(scanf("%d",&tt); tt--; solve());
solve();
return 0;
}

D. Maximum path

如果又往右走又往左走很麻烦,其实可以发现,连续往右走大于两步的情况都可以被分解成小于等于两步的走法,转移即可

view code
//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 1e5+7;
typedef long long int LL;
int n, A[4][MAXN];
LL f[4][MAXN];
inline void cmax(LL &x, LL y){ x = x > y ? x : y; }
void solve(){
scanf("%d",&n);
memset(f,-0x3f,sizeof(f));
for(int i = 1; i <= 3; i++) for(int j = 1; j <= n; j++) scanf("%d",&A[i][j]);
f[1][1] = A[1][1]; f[2][1] = f[1][1] + A[2][1]; f[3][1] = f[2][1] + A[3][1];
f[3][2] = 0ll + A[1][1] + A[1][2] + A[2][2] + A[2][1] + A[3][1] + A[3][2];
for(int i = 1; i < n; i++){
cmax(f[2][i+1],f[2][i] + A[2][i+1]);
cmax(f[1][i+1],f[1][i] + A[1][i+1]);
cmax(f[3][i+1],f[3][i] + A[3][i+1]);
cmax(f[2][i+1],f[1][i] + A[1][i+1] + A[2][i+1]);
cmax(f[2][i+1],f[3][i] + A[3][i+1] + A[2][i+1]);
cmax(f[1][i+1],f[2][i] + A[2][i+1] + A[1][i+1]);
cmax(f[3][i+1],f[2][i] + A[2][i+1] + A[3][i+1]);
cmax(f[1][i+1],f[3][i] + A[3][i+1] + A[2][i+1] + A[1][i+1]);
cmax(f[3][i+1],f[1][i] + A[1][i+1] + A[2][i+1] + A[3][i+1]);
if(i + 2 > n) continue;
cmax(f[1][i+2],f[3][i] + A[3][i+1] + A[3][i+2] + A[2][i+2] + A[2][i+1] + A[1][i+1] + A[1][i+2]);
cmax(f[3][i+2],f[1][i] + A[1][i+1] + A[1][i+2] + A[2][i+2] + A[2][i+1] + A[3][i+1] + A[3][i+2]);
}
cout << f[3][n] << endl;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("Local.in","r",stdin);
freopen("ans.out","w",stdout);
#endif
solve();
return 0;
}

E. Radio stations

因为两个接触的距离限制中半径要取\(\min\),所以考虑按半径大到小排序,把所有位置离散化一下,由于\(k\le 10\)然后每次只需要找对应的频率区间在可影响范围内有多少点即可,然后每次再把枚举的点放到对应的线段树里去

这里考虑动态开点权值线段树来做

view code
//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 5e5+7; vector<int> vec;
int n, k;
pair<pair<int,int>,int> sta[MAXN];
struct segtree{
int root[MAXN], sum[MAXN<<5], ls[MAXN<<5], rs[MAXN<<5], tot;
#define pushup(rt) sum[rt] = sum[ls[rt]] + sum[rs[rt]]
void modify(int l, int r, int pos, int &rt){
if(!rt) rt = ++tot;
sum[rt] += 1;
if(l+1==r) return;
int mid = (l + r) >> 1;
if(pos<mid) modify(l,mid,pos,ls[rt]);
else modify(mid,r,pos,rs[rt]);
}
int Q(int L, int R, int l, int r, int rt){
if(L>=r or l>=R) return 0;
if(L<=l and r<=R) return sum[rt];
int mid = (l + r) >> 1;
return Q(L,R,l,mid,ls[rt]) + Q(L,R,mid,r,rs[rt]);
}
}ST;
int exc(int x){ return lower_bound(vec.begin(),vec.end(),x) - vec.begin() + 1; }
void solve(){
scanf("%d %d",&n,&k);
for(int i = 1; i <= n; i++){
scanf("%d %d %d",&sta[i].first.first,&sta[i].second,&sta[i].first.second);
vec.push_back(sta[i].first.first-sta[i].second);
vec.push_back(sta[i].first.first+sta[i].second);
vec.push_back(sta[i].first.first);
}
sort(vec.begin(),vec.end());
vec.erase(unique(vec.begin(),vec.end()),vec.end());
sort(sta+1,sta+1+n,[](const pair<pair<int,int>,int> &A, const pair<pair<int,int>,int> &B){
return A.second > B.second;
});
long long int ret = 0;
for(int i = 1; i <= n; i++){
int p = exc(sta[i].first.first);
int l = exc(sta[i].first.first-sta[i].second);
int r = exc(sta[i].first.first+sta[i].second);
for(int f = max(1,sta[i].first.second-k); f <= sta[i].first.second+k; f++) ret += ST.Q(l,r+1,1,MAXN,ST.root[f]);
ST.modify(1,MAXN,p,ST.root[sta[i].first.second]);
}
cout << ret << endl;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("Local.in","r",stdin);
freopen("ans.out","w",stdout);
#endif
solve();
return 0;
}

F. Tree nesting

在大树里面找小树,大树随意定根,接下来我们枚举小树的根,如果某个小树和之前枚举的同构了就直接跳过同构当然用树哈希来判断,,然后用小树和大树匹配,令\(f[i][j]\)表示大树的节点\(i\)和小树的节点\(v\)匹配的方案数,接下来我们对小树\(dfs\)一遍,每次枚举和当且节点匹配的大树节点

当当前点是小树的叶子节点石,方案数显然是\(1\)

否则考虑状压\(DP\)转移,假设当前石小树的\(u\)节点和大树的\(x\)节点匹配,那么找出两者所有的儿子,然后\(dp[i][msk]\)表示当前枚举到\(x\)的第\(i\)个儿子,当前已经匹配的\(u\)的子节点集合为\(msk\)的方案数,转移很好转,如果\(u\)的子节点有同构又要除掉阶乘,否则会有重复计算

view code
//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 1111;
const int MOD = 1e9+7;
vector<int> GS[MAXN], GT[MAXN];
int n, m, fac[20], inv[20], rfac[20], prime[] = {0,2,3,5,7,11,13,17,19,23,29,31,37,41};
int ret, sz[20], hax[20], fas[MAXN], fat[20];
set<int> vishash;
void dfss(int u, int par){
fas[u] = par;
for(int v : GS[u]) if(v!=par) dfss(v,u);
}
void dfs(int u, int par){
sz[u] = hax[u] = 1;
fat[u] = par;
for(int v : GT[u]){
if(v==par) continue;
dfs(v,u);
sz[u] += sz[v];
hax[u] = (hax[u] + hax[v] * prime[sz[v]]) % MOD;
}
}
int f[20][MAXN];
void match(int u){
for(int v : GT[u]) if(v!=fat[u]) match(v);
if((GT[u].size()==1 and fat[u]) or GT[u].empty()){
for(int i = 1; i <= n; i++) f[u][i] = 1;
return;
}
vector<int> sont;
map<int,int> cnt;
for(int v : GT[u]) if(v!=fat[u]){
sont.push_back(v);
cnt[hax[v]]++;
}
int ff = 1;
for(auto p : cnt) ff = (1ll * ff * rfac[p.second]) % MOD;
for(int x = 1; x <= n; x++){
// try match u and x
vector<int> sons;
for(int v : GS[x]) if(v!=fas[x]) sons.push_back(v);
vector<vector<int> > dp(2,vector<int>(1<<sont.size()));
dp[0][0] = 1; int tag = 1;
for(int i = 0; i < (int)sons.size(); i++, tag ^= 1){
dp[tag] = dp[tag^1];
for(int msk = 0; msk < (1<<sont.size()); msk++){
for(int bit = 0; bit < (int)sont.size(); bit++){
if(msk>>bit&1) continue;
dp[tag][msk|(1<<bit)] = (dp[tag][msk|(1<<bit)] + 1ll * dp[tag^1][msk] * f[sont[bit]][sons[i]]) % MOD;
}
}
}
f[u][x] = 1ll * dp[tag^1][(1<<sont.size())-1] * ff % MOD;
}
}
void test(int id){
dfs(id,0);
if(vishash.count(hax[id])) return;
vishash.insert(hax[id]);
memset(f,0,sizeof(f));
match(id);
for(int i = 1; i <= n; i++) ret = (ret + f[id][i]) % MOD;
}
void solve(){
scanf("%d",&n);
for(int i = 1; i < n; i++){
int u, v; scanf("%d %d",&u,&v);
GS[u].push_back(v);
GS[v].push_back(u);
}
scanf("%d",&m);
for(int i = 1; i < m; i++){
int u, v; scanf("%d %d",&u,&v);
GT[u].push_back(v);
GT[v].push_back(u);
}
dfss(1,0);
for(int i = 1; i <= m; i++) test(i);
cout << ret << endl;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("Local.in","r",stdin);
freopen("ans.out","w",stdout);
#endif
fac[0] = rfac[0] = inv[1] = 1;
for(int i = 1; i < 20; i++) fac[i] = 1ll * i * fac[i-1] % MOD;
for(int i = 2; i < 20; i++) inv[i] = 1ll * (MOD - MOD / i) * inv[MOD%i] % MOD;
for(int i = 1; i < 20; i++) rfac[i] = 1ll * inv[i] * rfac[i-1] % MOD;
solve();
return 0;
}

Educational Codeforces Round 17的更多相关文章

  1. Educational Codeforces Round 17 颓废记

    又被虐了... (记一次惨痛的Codeforces) 好不容易登上去了Codeforces,22:35准时开打 第一题,一看:这不SB题嘛?直接枚举因数上啊.9min才过掉了pretest 第二题.. ...

  2. Educational Codeforces Round 17 D. Maximum path DP

    题目链接:http://codeforces.com/contest/762/problem/D 多多分析状态:这个很明了 #include<bits/stdc++.h> using na ...

  3. Educational Codeforces Round 17 C. Two strings 打表二分

    C. Two strings time limit per test 2 seconds memory limit per test 256 megabytes input standard inpu ...

  4. Codeforces Educational Codeforces Round 17 Problem.A kth-divisor (暴力+stl)

    You are given two integers n and k. Find k-th smallest divisor of n, or report that it doesn't exist ...

  5. Educational Codeforces Round 71 (Rated for Div. 2)-E. XOR Guessing-交互题

    Educational Codeforces Round 71 (Rated for Div. 2)-E. XOR Guessing-交互题 [Problem Description] ​ 总共两次询 ...

  6. [Educational Codeforces Round 16]E. Generate a String

    [Educational Codeforces Round 16]E. Generate a String 试题描述 zscoder wants to generate an input file f ...

  7. [Educational Codeforces Round 16]D. Two Arithmetic Progressions

    [Educational Codeforces Round 16]D. Two Arithmetic Progressions 试题描述 You are given two arithmetic pr ...

  8. [Educational Codeforces Round 16]C. Magic Odd Square

    [Educational Codeforces Round 16]C. Magic Odd Square 试题描述 Find an n × n matrix with different number ...

  9. [Educational Codeforces Round 16]B. Optimal Point on a Line

    [Educational Codeforces Round 16]B. Optimal Point on a Line 试题描述 You are given n points on a line wi ...

随机推荐

  1. 安装Android Studio遇到的问题

    1. 学习视频 视频链接:https://www.bilibili.com/video/BV1jW411375J?p=2 2. Android Studio1.5.1的下载地址: http://www ...

  2. Java 安全之Weblogic 2017-3248分析

    Java 安全之Weblogic 2017-3248分析 0x00 前言 在开头先来谈谈前面的绕过方式,前面的绕过方式分别使用了streamMessageImpl 和MarshalledObject对 ...

  3. oracle 11g 安装与卸载

    安装 点击是,这是位数不一致,但可用. 桌面类――这种安装方式一般适用于台式机和笔记本.它包含一个最小数据库和最低的配置需求. 服务器类――这种安装方式适用于服务器,例如,它会向您提供数据中心和用于支 ...

  4. 【Software Test】Basic Of ST

    文章目录 Learning Objective Introduction Software Applications Before Software Testing What is testing? ...

  5. kubernets之pod的标签

    一     如何查看pod 的日志 1 通过执行命令查看日志信息 kubectl logs pod_name 二    创建带有标签的pod,一个范例的pod创建yaml文件如下所示 2.1 创建带有 ...

  6. Netty学习:ChannelHandler执行顺序详解,附源码分析

    近日学习Netty,在看书和实践的时候对于书上只言片语的那些话不是十分懂,导致尝试写例子的时候遭遇各种不顺,比如decoder和encoder还有HttpObjectAggregator的添加顺序,研 ...

  7. pycharm工具的使用

    一.Pycharm常用快捷键 快捷键 作用 备注  ctrl + win + 空格  自动提示并导包  连按两次  ctrl + alt + 空格  自动提示并导包  连按两次  Alt + Ente ...

  8. Javadoc命令与API

    Javadoc命令与API Javadoc工具会抽取类,成员,方法的文档注释生成与这个类配套的API帮助文档 Javadoc命令和文档注释小公司基本不用,但我们应养成良好的编码习惯,所以还是了解一下 ...

  9. Python-Flask搭建Web项目

    最近因项目需要,学习了用flask搭建web项目,以下是自己的使用感悟 Flask框架结构 static:存储一些静态资源 templates:存储对应的view app.py:涉及到页面的跳转,以及 ...

  10. GStreamer环境搭建篇

    GStreamer是一套强大的多媒体中间件系统,跟FFmpeg功能类似. 各个Linux发行版(Ubuntu,fedora),大都集成了GStreamer相关工具,而作为软件层次结构最上层的播放器,几 ...