ACM-ICPC 2018 徐州赛区网络预赛

A.Hard to prepare

枚举第一个选的,接下来的那个不能取前一个的取反

\(DP[i][0]\)表示选和第一个相同的

\(DP[i][1]\)表示选和第一个取反的

\(DP[i][2]\)表示选其他的

状态转移方程直接看代码好了

//#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 = 1e6+7;
typedef long long int LL;
const LL MOD = 1e9+7;
int n,k;
LL qpow(LL a, LL b){
LL ret = 1;
while(b){
if(b&1) ret = ret * a % MOD;
b >>= 1;
a = a * a % MOD;
}
return ret;
}
LL f[2][3];
void solve(){
cin >> n >> k;
LL pk = qpow(2,k);
LL pk_1 = (pk-1+MOD)%MOD;
LL pk_2 = (pk-2+MOD)%MOD;
LL pk_3 = (pk-3+MOD)%MOD;
int ID = 0;
f[0][0] = 1; f[0][1] = 0; f[0][2] = 0;
//0 自身 1 自身取反 2.其他
for(int i = 2; i <= n; i++){
ID ^= 1;
f[ID][0] = (f[ID^1][0]+f[ID^1][2]) % MOD;
f[ID][1] = (f[ID^1][1]+f[ID^1][2]) % MOD;
f[ID][2] = (f[ID^1][0]*pk_2%MOD + f[ID^1][1]*pk_2%MOD + f[ID^1][2]*pk_3%MOD) % MOD;
}
cout << pk * (f[ID][0] + f[ID][2]) % MOD << endl;
}
int main(){
____();
int T;
for(cin >> T; T; T--) solve();
return 0;
}

B.BE, GE or NE

Game + DP || 记忆化搜索

到每个人选的时候必然在三种选择中选择最合适自己的,记忆化到每个位置\(i\)当前值是\(x\)的情况下的解

//#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 D = 100;
const int INF = 0x3f3f3f3f;
int n,f[MAXN][D<<2],m,l,r;
tuple<int,int,int> ops[MAXN];
int ending(int score){
if(score>=r) return 1;
if(score<=l) return -1;
return 0;
}
int search(int pos, int v){
if(f[pos][v+D]!=INF) return f[pos][v+D];
if(pos==n+1) return f[pos][v+D] = ending(v);
vector<int> opt;
if(get<0>(ops[pos])) opt.emplace_back(search(pos+1,min(D,v+get<0>(ops[pos]))));
if(get<1>(ops[pos])) opt.emplace_back(search(pos+1,max(-D,v-get<1>(ops[pos]))));
if(get<2>(ops[pos])) opt.emplace_back(search(pos+1,-v));
sort(opt.begin(),opt.end());
if(pos&1) f[pos][v+D] = opt.back();
else f[pos][v+D] = opt.front();
return f[pos][v+D];
}
int main(){
____();
cin >> n >> m >> r >> l;
for(int i = 1; i <= n; i++) cin >> get<0>(ops[i]) >> get<1>(ops[i]) >> get<2>(ops[i]);
memset(f,0x3f,sizeof(f));
int ret = search(1,m);
if(ret==-1) cout << "Bad Ending" << endl;
else if(ret==0) cout << "Normal Ending" << endl;
else if(ret==1) cout << "Good Ending" << endl;
return 0;
}

C.Cacti Lottery

D.Easy Math

杜教筛

\[计算f(m,n) = \sum_{i=1}^{m}\mu(in)
\]
\[f(m,n)=\sum_{i=1}^{m}\mu(in)
\]
\[= \sum_{i=1}^{m}\mu(i)\mu(n)[gcd(i,n)==1]
\]
\[= \sum_{i=1}^{m}\mu(i)\mu(n)\sum_{d|gcd(i,n)}\mu(d)
\]
\[= \mu(n)\sum_{i=1}^{m}\mu(i)\sum_{d|gcd(i,n)}\mu(d)
\]
\[=\mu(n)\sum_{d|n}\mu(d)\sum_{i=1}^{\lfloor \frac{m}{d}\rfloor}\mu(id)
\]
\[=\mu(n)\sum_{d|n}\mu(d)f(\lfloor\frac{m}{d}\rfloor,d)
\]

递归计算即可

边界条件为:

\(m==1\)时 返回\(\mu(n)\)

\(m==0\)时 返回\(0\)

\(n==1\)时 杜教筛计算\(\sum_{i=1}^{m}\mu(i)\)

//#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;
const int MAXN = 5e6+7;
vector<LL> prime;
bool npm[MAXN];
LL mu[MAXN],mus[MAXN],w[1<<11];
map<LL,LL> MU;
vector<LL> fact;
vector<int> subset[1<<11];
void preprocess(){
mu[1] = 1;
for(LL i = 2; i < MAXN; i++){
if(!npm[i]){
prime.emplace_back(i);
mu[i] = -1;
}
for(int j = 0; j < (int)prime.size(); j++){
if(i*prime[j]>=MAXN) break;
mu[i*prime[j]] = -mu[i];
npm[i*prime[j]] = true;
if(i%prime[j]==0){
mu[i*prime[j]] = 0;
break;
}
}
}
for(int i = 1; i < MAXN; i++) mus[i] = mus[i-1] + mu[i];
for(int i = 0; i < (1<<11); i++){
for(int j = 0; j <= i; j++){
if((i&j)==j) subset[i].push_back(j);
}
}
for(int msk = 0; msk < (1<<(int)fact.size()); msk++){
w[msk] = 1;
for(int i = 0; i < (int)fact.size(); i++){
if(msk&(1<<i)) w[msk] *= fact[i];
}
}
}
LL calmus(LL x){
if(x<MAXN) return mus[x];
if(MU.count(x)) return MU[x];
LL tot = 1;
for(LL i = 2; i <= x; i++){
LL j = x / (x / i);
tot -= (j - i + 1) * calmus(x / i);
i = j;
}
return MU[x] = tot;
}
bool init(LL n){
for(LL i = 2; i * i <= n; i++){
if(n%i==0){
fact.emplace_back(i);
n /= i;
if(n%i==0) return false;
}
}
if(n!=1) fact.emplace_back(n);
return true;
}
LL solve(LL m, int MSK){
if(!MSK) return calmus(m);
if(m==0) return 0;
if(m==1) return ((__builtin_popcount(MSK)&1)?-1:1);
LL ret = 0;
for(int msk : subset[MSK]){
ret += ((__builtin_popcount(msk)&1)?-1:1) * solve(m/w[msk],msk);
}
return ret * ((__builtin_popcount(MSK)&1)?-1:1);
}
int main(){
LL m, n;
cin >> m >> n;
if(!init(n)) cout << 0 << endl;
else preprocess(), cout << solve(m,(1<<fact.size())-1) << endl;
return 0;
}

E.End Fantasy VIX

F.Features Track

map搞一下就好了

//#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;
map<pair<int,int>,int> msk[2];
void solve(){
int ret = 1, n;
scanf("%d",&n);
int ID = 0;
msk[0].clear(); msk[1].clear();
for(int i = 1; i <= n; i++){
int k; scanf("%d",&k);
ID ^= 1;
msk[ID].clear();
for(int j = 1; j <= k; j++){
pair<int,int> p; scanf("%d %d",&p.first,&p.second);
if(msk[ID^1].count(p)) msk[ID].insert(make_pair(p,msk[ID^1].at(p)+1));
else msk[ID].insert(make_pair(p,1));
ret = max(ret,msk[ID].at(p));
}
}
printf("%d\n",ret);
}
int main(){
int T;
for(scanf("%d",&T); T; T--) solve();
return 0;
}

G.Trace

线段树+离散化

可以把\(x\)和\(y\)两个维度分开来做

以计算\(x\)轴方向总长度为例

从最后一个\(wave\)开始向前遍历,找在他之后且\(y\)方向坐标位置大于当前\(wave\)的\(x\)的最大值,贡献就是当前的\(x\),减去在他之后的最大的\(x\),可以通过离散化+线段树的方法来做

//#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 = 5e4+7;
typedef long long int LL;
int n;
class SegmentTree{
private:
int l[MAXN<<2],r[MAXN<<2],maxx[MAXN<<2];
#define ls(rt) rt << 1
#define rs(rt) rt << 1 | 1
#define pushup(rt) maxx[rt] = max(maxx[ls(rt)],maxx[rs(rt)])
public:
void build(int L, int R, int rt = 1){
l[rt] = L; r[rt] = R;
maxx[rt] = 0;
if(L+1==R) return;
int mid = (L+R) >> 1;
build(L,mid,ls(rt)); build(mid,R,rs(rt));
}
void update(int pos, int x, int rt = 1){
if(l[rt]+1==r[rt]){
maxx[rt] = max(maxx[rt],x);
return;
}
int mid = (l[rt] + r[rt]) >> 1;
if(pos<mid) update(pos,x,ls(rt));
else update(pos,x,rs(rt));
pushup(rt);
}
int qmax(int L, int R, int rt = 1){
if(l[rt]>=R or L>=r[rt]) return 0;
if(L<=l[rt] and r[rt]<=R) return maxx[rt];
return max(qmax(L,R,ls(rt)),qmax(L,R,rs(rt)));
}
}ST;
void solve(vector<pair<int,int> > &rect, LL &ret){
vector<int> vec;
for(int i = 0; i < (int)rect.size(); i++) vec.emplace_back(rect[i].second);
sort(vec.begin(),vec.end());
vec.erase(unique(vec.begin(),vec.end()),vec.end());
ST.build(1,vec.size()+1);
for(int i = 0; i < (int)rect.size(); i++){
int y = lower_bound(vec.begin(),vec.end(),rect[i].second) - vec.begin() + 1;
ret += rect[i].first - ST.qmax(y,vec.size()+1);
ST.update(y,rect[i].first);
}
}
int main(){
____();
cin >> n;
vector<pair<int,int> > rect(n);
for(int i = 0; i < n; i++) cin >> rect[i].first >> rect[i].second;
reverse(rect.begin(),rect.end());
LL ret = 0;
solve(rect,ret);
for(int i = 0; i < n; i++) swap(rect[i].first,rect[i].second);
solve(rect,ret);
cout << ret << endl;
return 0;
}

H.Ryuji doesn't want to study

线段树

//#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,m;
class SegmentTree{
private:
int l[MAXN<<2], r[MAXN<<2];
LL sum1[MAXN<<2],sum2[MAXN<<2];
#define ls(rt) rt << 1
#define rs(rt) rt << 1 | 1
void pushup(int rt){
sum1[rt] = sum1[ls(rt)] + sum1[rs(rt)];
sum2[rt] = sum2[ls(rt)] + sum2[rs(rt)];
}
public:
void build(int L, int R, int rt = 1){
l[rt] = L; r[rt] = R;
if(L+1==R){
cin >> sum1[rt];
sum2[rt] = sum1[rt] * (n + 1ll - L);
return;
}
int mid = (L+R) >> 1;
build(L,mid,ls(rt)); build(mid,R,rs(rt));
pushup(rt);
}
void update(int pos, int x, int rt = 1){
if(l[rt] + 1 == r[rt]){
sum1[rt] = x;
sum2[rt] = sum1[rt] * (n + 1ll - l[rt]);
return;
}
int mid = (l[rt] + r[rt]) >> 1;
if(pos<mid) update(pos,x,ls(rt));
else update(pos,x,rs(rt));
pushup(rt);
}
pair<LL,LL> query(int L, int R, int rt = 1){
if(l[rt]>=R or L>=r[rt]) return make_pair(0,0);
if(L<=l[rt] and r[rt]<=R) return make_pair(sum1[rt],sum2[rt]);
auto p1 = query(L,R,ls(rt));
auto p2 = query(L,R,rs(rt));
return make_pair(p1.first+p2.first,p1.second+p2.second);
}
}ST;
//维护两个值 1.A[i], 2.A[i] * (n+1-i) 区间和
int main(){
____();
cin >> n >> m;
ST.build(1,n+1);
while(m--){
int op,a,b;
cin >> op >> a >> b;
if(op==1){
auto p = ST.query(a,b+1);
cout << p.second - p.first * (n - b) << endl;
}
else ST.update(a,b);
}
return 0;
}

I.Characters with Hash

签到

//#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 = 1e6+7;
int n;
char s[MAXN],st[2];
void solve(){
cin >> n >> st >> s;
for(int i = 0; i < n; i++){
if(s[i]!=st[0]){
if(abs(s[i]-st[0])>=10) cout << (n-i) * 2 << endl;
else cout << (n-i) * 2 - 1 << endl;
return;
}
}
cout << 1 << endl;
}
int main(){
____();
int T; for(cin >> T; T; T--) solve();
return 0;
}

J.Maze Designer

因为任意两个点只存在唯一路径,所以这是个树形结构,现在要求建的墙花费最小,那么就是要求不建的花费最大,所以就是要找出最大生成树,然后对于每次询问就是询问树上两点的距离

//#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 = 555;
typedef long long int LL;
int n,m,num,root[MAXN*MAXN],depth[MAXN*MAXN],par[MAXN*MAXN][20];;
int ID(int x, int y){ return (x - 1) * m + y; }
int findx(int x){ return root[x]==x ? root[x] : root[x] = findx(root[x]); }
pair<LL,pair<int,int>> edge[MAXN*MAXN*2];
vector<int> G[MAXN*MAXN];
int LCA(int u, int v){
if(depth[u]<depth[v]) swap(u,v);
for(int i = 0; depth[u] - depth[v]; i++) if((depth[u]-depth[v])&(1<<i)) u = par[u][i];
if(u==v) return u;
for(int i = 19; i >= 0; i--) if(par[u][i]!=par[v][i]){
u = par[u][i];
v = par[v][i];
}
return par[u][0];
}
void dfs(int u, int f){
depth[u] = depth[f] + 1;
par[u][0] = f;
for(int i = 1; par[u][i-1]; i++) par[u][i] = par[par[u][i-1]][i-1];
for(int v : G[u]) if(v!=f) dfs(v,u);
}
int solve(int u, int v){
int lca = LCA(u,v);
return depth[u] + depth[v] - 2 * depth[lca];
}
int main(){
scanf("%d %d",&n,&m);
for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++){
char ds[2]; LL cost;
scanf("%s %lld",ds,&cost);
if(ds[0]!='X') edge[++num] = make_pair(cost,make_pair(ID(i,j),ID(i+1,j)));
scanf("%s %lld",ds,&cost);
if(ds[0]!='X') edge[++num] = make_pair(cost,make_pair(ID(i,j),ID(i,j+1)));
}
for(int i = 1; i <= n * m; i++) root[i] = i;
sort(edge+1,edge+1+num,greater<pair<LL,pair<int,int>>>());
for(int i = 1; i <= num; i++){
int u = edge[i].second.first, v = edge[i].second.second;
int fu = findx(u), fv = findx(v);
if(fu==fv) continue;
root[fu] = fv;
G[u].emplace_back(v); G[v].emplace_back(u);
}
int q; scanf("%d",&q);
dfs(1,0);
while(q--){
int x1, y1, x2, y2;
scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
printf("%d\n",solve(ID(x1,y1),ID(x2,y2)));
}
return 0;
}

K.Morgana Net

ACM-ICPC 2018 徐州赛区网络预赛(8/11)的更多相关文章

  1. ACM-ICPC 2018 徐州赛区网络预赛 G. Trace (思维,贪心)

    ACM-ICPC 2018 徐州赛区网络预赛 G. Trace (思维,贪心) Trace 问答问题反馈 只看题面 35.78% 1000ms 262144K There's a beach in t ...

  2. ACM-ICPC 2018 徐州赛区网络预赛 J. Maze Designer (最大生成树+LCA求节点距离)

    ACM-ICPC 2018 徐州赛区网络预赛 J. Maze Designer J. Maze Designer After the long vacation, the maze designer ...

  3. 计蒜客 1460.Ryuji doesn't want to study-树状数组 or 线段树 (ACM-ICPC 2018 徐州赛区网络预赛 H)

    H.Ryuji doesn't want to study 27.34% 1000ms 262144K   Ryuji is not a good student, and he doesn't wa ...

  4. ACM-ICPC 2018 徐州赛区网络预赛 B(dp || 博弈(未完成)

    传送门 题面: In a world where ordinary people cannot reach, a boy named "Koutarou" and a girl n ...

  5. ACM-ICPC 2018 徐州赛区网络预赛 B. BE, GE or NE

    In a world where ordinary people cannot reach, a boy named "Koutarou" and a girl named &qu ...

  6. ACM-ICPC 2018 徐州赛区网络预赛 H. Ryuji doesn't want to study

    262144K   Ryuji is not a good student, and he doesn't want to study. But there are n books he should ...

  7. ACM-ICPC 2018 徐州赛区网络预赛 F. Features Track

    262144K   Morgana is learning computer vision, and he likes cats, too. One day he wants to find the ...

  8. ACM-ICPC 2018 徐州赛区网络预赛 I. Characters with Hash

    Mur loves hash algorithm, and he sometimes encrypt another one's name, and call him with that encryp ...

  9. ACM-ICPC 2018 徐州赛区网络预赛 D 杜教筛 前缀和

    链接 https://nanti.jisuanke.com/t/31456 参考题解  https://blog.csdn.net/ftx456789/article/details/82590044 ...

随机推荐

  1. LeetCode278 第一个错误的版本

    你是产品经理,目前正在带领一个团队开发新的产品.不幸的是,你的产品的最新版本没有通过质量检测.由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的. 假设你有 n 个版本 [1, ...

  2. GitHub README.md文本编写指南

    标题 在文字前写#,注意文字与#之间有一个空格 # 一级标题## 二级标题### 三级标题 以此类推或者用连续的减号或等号写在文字之下: 标题- 粗体斜体 **这个是粗体*这个是斜体****这个是粗体 ...

  3. 为什么会有 AtomicReference ?

    我把自己以往的文章汇总成为了 Github ,欢迎各位大佬 star https://github.com/crisxuan/bestJavaer 我们之前了解过了 AtomicInteger.Ato ...

  4. Inlook - 你的私人工作助理 V1.0.0.2

    Inlook - Your personal assistant 中文版|English version Introduction Inlook是为在桌面上直观地提醒用户收到未读邮件和日程安排而开发的 ...

  5. springAOP的概述及使用

    Spring AOP SpringAOP是Spring中非常重要的功能模块之一,该模块提供了面向切面编程,在事务处理,日志记录,安全控制等操作中广泛使用. SpringAOP的基本概念 AOP的概念 ...

  6. Mysql简要概述

    Mysql学习笔记 Mysql简介: ​ Mysql是一个轻量级关系型数据库管理系统,由瑞典Mysql AB公司开发,目前属于Oracle公司.目前Mysql被广泛地应用在Internet上的中小型网 ...

  7. 2021年【线上】lammps分子动力学技术实战培训班

    材料模拟分子动力学课程 3月19号--22号 远程在线课 lammps分子动力学课程 3月12号--15号 远程在线课 第一性原理VASP实战课 3月25号-28号 远程在线课 量子化学Gaussia ...

  8. Py其他内置函数,文件修改

    其他内置函数 1.abs函数,取绝对值 print(abs(-1)) 2.all函数,判断可迭代对象是否全为真,有假直接假 假:0,'',None print(all([1,2,'1'])) prin ...

  9. Linux安装MYSQL并部署主从复制集群

    主节点部署 安装数据库 Ubuntu apt-get install mysql-server -y systemctl start mysql systemctl enabled mysql Cen ...

  10. codeup 1934 查找元素

    题目描述: 输入一个数n,然后输入n个数值各不相同,再输入一个值x,输出这个值在这个数组中的下标(从0开始,若不在数组中则输出-1. 输入: 测试数据有多组,输入n(1<=n<=200), ...