2017-2018 ACM-ICPC, Asia Daejeon Regional Contest
只打了三个小时。
A. Broadcast Stations
B. Connect3
补题:zz
题解:因为格子是4*4的,而且每次落子的位置最多是只有四个,再加上剪枝,情况不会很多,直接爆搜就行了,再用三进制记录已经合法的情况,去掉重复的情况就行了。(用vs2017交会ac,但c++17会wa1,很奇怪)
//#pragma comment(linker, "/STACK:102400000,102400000")
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<string>
#include<math.h>
#include<cmath>
#include<time.h>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<algorithm>
#include<numeric>
#include<stack>
#include<bitset>
#include<unordered_map>
const int maxn = 0x3f3f3f3f;
const double EI = 2.71828182845904523536028747135266249775724709369995957496696762772407663035354594571382178525166427;
const double PI = 3.141592653589793238462643383279;
//#ifdef TRUETRUE
//#define gets gets_s
//#endif
using namespace std;
int a, b;
int ans;
map<int, int>mp;
bool Judge(int c[][], int aa, int bb, int pos)
{
if (aa == a && bb == b && pos == )
{
return false;
}
int cc[][], i, j;
for (i = ; i <= ; i++)
{
for (j = ; j <= ; j++)
{
cc[i + ][j + ] = c[i][j];
}
}
aa++;
bb++;
bool flag = false;
if (cc[aa][bb] == cc[aa - ][bb] && cc[aa][bb] == cc[aa - ][bb]
|| cc[aa][bb] == cc[aa + ][bb] && cc[aa][bb] == cc[aa + ][bb]
|| cc[aa][bb] == cc[aa][bb - ] && cc[aa][bb] == cc[aa][bb - ]
|| cc[aa][bb] == cc[aa][bb + ] && cc[aa][bb] == cc[aa][bb + ]
|| cc[aa][bb] == cc[aa + ][bb + ] && cc[aa][bb] == cc[aa + ][bb + ]
|| cc[aa][bb] == cc[aa - ][bb - ] && cc[aa][bb] == cc[aa - ][bb - ]
|| cc[aa][bb] == cc[aa - ][bb] && cc[aa][bb] == cc[aa + ][bb]
|| cc[aa][bb] == cc[aa][bb - ] && cc[aa][bb] == cc[aa][bb + ]
|| cc[aa][bb] == cc[aa - ][bb - ] && cc[aa][bb] == cc[aa + ][bb + ]
|| cc[aa][bb] == cc[aa - ][bb + ] && cc[aa][bb] == cc[aa - ][bb + ]
|| cc[aa][bb] == cc[aa + ][bb - ] && cc[aa][bb] == cc[aa + ][bb - ]
|| cc[aa][bb] == cc[aa - ][bb + ] && cc[aa][bb] == cc[aa + ][bb - ])
{
flag = true;
}
if (flag && pos == && aa - == a && bb - == b)
{
int tmp = ;
for (i = ;i <= ;i++)
{
for (j = ;j <= ;j++)
{
tmp *= ;
tmp += c[i][j];
}
}
if (!mp[tmp])
{
ans++;
mp[tmp] = ;
}
return false;
}
if (flag || (!flag && aa - == a && bb - == b))
{
return false;
}
else
{
return true;
}
}
void f(int c[][], int d[], int pos)
{
int i;
for (i = ; i <= ; i++)
{
if (d[i] <= )
{
c[d[i]][i] = pos;
int dd[][];
for (int ii = ;ii <= ;ii++)
{
memcpy(dd[ii], c[ii], sizeof(c[ii]));
}
if (Judge(dd, d[i], i, pos))
{
d[i]++;
f(dd, d, - pos);
d[i]--;
}
c[d[i]][i] = ;
}
}
}
void init(void)
{
mp.clear();
}
int main(void)
{
//ios::sync_with_stdio(false);
int x;
while (~scanf("%d %d %d", &x, &a, &b))
{
init();
int c[][];
int d[] = { ,,,,,,,,, };
d[x]++;
memset(c, , sizeof(c));
c[][x] = ;
ans = ;
f(c, d, );
printf("%d\n", ans);
}
return ;
}
C. Game Map
题意:给定一张无向图,要求找出一个最长的序列,使得这个序列的度数是严格递增的。
思路:对于每一个点来说,这个点在序列中的位置可以是1,也可以是从和它相邻的且读书小于它的点转移过来的,所以枚举度数从小到大的点即可。
#include<bits/stdc++.h>
#define clr(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const int maxn=;
vector<int>ve[];
unordered_map<int,int>mp[];
int c[],de[];
struct s
{
int de,id;
}z[];
inline bool comp(s a,s b)
{
return a.de <b.de;
}
int main(){
int n,m,i,z1,z2,si,j,ans;
while(~scanf("%d %d",&n,&m))
{
for(i = ;i <= n;i++)
{
ve[i].clear();
mp[i].clear();
c[i] = ;
z[i].de = ;
z[i].id = i;
de[i] = ;
}
for(i = ;i < m;i++)
{
scanf("%d %d",&z1,&z2);
if(z1 > z2)
{
int r = z1;
z1 = z2;
z2 = r;
}
if(z1 != z2 && !mp[z1][z2])
{
mp[z1][z2] = ;
ve[z1].push_back(z2);
ve[z2].push_back(z1);
z[z1].de++;
z[z2].de++;
de[z1]++;
de[z2]++;
}
}
sort(z,z + n,comp);
ans = ;
for(i = ;i < n;i++)
{
si = ve[z[i].id].size();
//printf(" %d %d\n",z[i].id,z[i].de);
for(j = ;j < si;j++)
{
//printf(" %d %d %d\n",z[i].de,z[ve[z[i].id][j]].de,ve[z[i].id][j]);
if(z[i].de > de[ve[z[i].id][j]])
{
c[z[i].id] = max(c[z[i].id],c[ve[z[i].id][j]] + );
}
}
//printf(" %d\n",c[z[i].id]);
ans = max(ans,c[z[i].id]);
}
printf("%d\n",ans);
}
}
D. Happy Number
#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<string>
#include<map>
#include<queue>
#include<vector>
#include<stack>
#define ll long long
#define maxn 4001000
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
int n,len;
map<int,int> mp;
ll read()
{
ll x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
void init()
{
scanf("%d",&n);
len=;
mp[n]=;
}
void work()
{
while()
{
int x=n,ans=;
while(x>)
{
ans+=(x%)*(x%);
x/=;
}
if(ans==)
{
printf("HAPPY");
return;
}
if(mp[ans]!=)
{
printf("UNHAPPY");
return;
}
else mp[ans]=++len;
n=ans;
}
}
int main()
{
init();
work();
}
E. How Many to Be Happy
补题:kk
一开始想了个假算法,没被队友hack,然后wa3?最近好像经常写假算法
对于这样最小生成树的题的选边问题,我们一定要考虑克鲁斯卡尔的过程,对于一条边权为$w$的边,如果他要在最小生成树上,那么前提条件是权值比他小的边不会把u到v所属的两个结合连接在一起,也就是说,现在我们要去掉一些权值小于$w$的边,让u和v分在不同的两个集合里面,想到这里就会想到最小割的模型,对于每条边,都把权值小于他的边加入到图里,然后求一个最小割就可以了。
所以,最小生成树的题一定要考虑克鲁斯卡尔!这真是一个神奇的算法,还有对数据范围要敏感,$n=100$也应该想到网络流。
#include<bits/stdc++.h>
#define clr(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll; const ll INFLL = 0x3f3f3f3f3f3f3f3f;
const int INF = 0x3f3f3f3f;
const int maxn = ; struct Edge {
int to, flow, nxt;
Edge(){}
Edge(int to, int nxt, int flow):to(to),nxt(nxt), flow(flow){}
}edge[maxn << ]; int head[maxn], dep[maxn];
int S, T;
int N, n, m, tot,ans; void Init(int n)
{
N = n;
for (int i = ; i < N; ++i) head[i] = -;
tot = ;
} void addv(int u, int v, int w, int rw = )
{
edge[tot] = Edge(v, head[u], w); head[u] = tot++;
edge[tot] = Edge(u, head[v], rw); head[v] = tot++;
} bool BFS()
{
for (int i = ; i < N; ++i) dep[i] = -;
queue<int>q;
q.push(S);
dep[S] = ;
while (!q.empty())
{
int u = q.front();
q.pop();
for (int i = head[u]; ~i; i = edge[i].nxt)
{
if (edge[i].flow && dep[edge[i].to] == -)
{
dep[edge[i].to] = dep[u] + ;
q.push(edge[i].to);
}
}
}
return dep[T] < ? : ;
} int DFS(int u, int f)
{
if (u == T || f == ) return f;
int w, used = ;
for (int i = head[u]; ~i; i = edge[i].nxt)
{
if (edge[i].flow && dep[edge[i].to] == dep[u] + )
{
w = DFS(edge[i].to, min(f - used, edge[i].flow));
edge[i].flow -= w;
edge[i ^ ].flow += w;
used += w;
if (used == f) return f;
}
}
if (!used) dep[u] = -;
return used;
} int Dicnic()
{
int ans = ;
while (BFS())
{
ans += DFS(S, INF);
}
return ans;
}
struct node{
int u,v,w;
friend bool operator<(const node &a,const node &b)
{
return a.w<b.w;
}
}a[maxn];
int main(){
while(cin>>n>>m)
{
for(int i=;i<=m;i++)
{
scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].w);
}
ans=;
sort(a+,a++m);
for(int i=;i<=m;i++)
{
Init(n+);
for(int j=;j<i;j++)
{
if(a[j].w>=a[i].w)break;
addv(a[j].u,a[j].v,);
addv(a[j].v,a[j].u,);
}
S=a[i].u,T=a[i].v;
ans+=Dicnic();
// printf("debug\n");
}
printf("%d\n",ans);
}
}
F. Philosphoer's Walk
题意:给定一张题目里描述的规模的图,输出走k布后的点。
思路:每一张图都能分解为四张规模一样的图,判断最终会在哪一张小图里和起止点的位置,之后再重复这个操作,直到2*2的图为止。
#include<bits/stdc++.h>
#define clr(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const int maxn=;
struct s
{
int a,b;
}in;
int Pow[];
int Node[][] = {,,,,,,,,,};
inline void init(void)
{
int i,tmp = ;
for(i = ;i <= ;i++)
{
Pow[i] = tmp;
tmp <<= ;
}
}
inline s f(int num,int step)
{
int pos,st;
s jk;
if(num == )
{
s tmp;
tmp.a = Node[step][];
tmp.b = Node[step][];
return tmp;
}
pos = (step - ) / (Pow[num - ] * Pow[num - ]);
st = (step - ) % (Pow[num - ] * Pow[num - ]) + ;
s nex = f(num - ,st);
if(pos == )
{
jk.a = + nex.b;
jk.b = + nex.a;
}
else if(pos == )
{
jk.a = + nex.a;
jk.b = Pow[num - ] + nex.b;
}
else if(pos == )
{
jk.a = Pow[num - ] + nex.a;
jk.b = Pow[num - ] + nex.b;
}
else
{
jk.a = Pow[num] + - nex.b;
jk.b = Pow[num - ] + - nex.a;
}
return jk;
}
int main(){
int n,m,i;
init();
while(~scanf("%d %d",&n,&m))
{
for(i = ;i <= ;i++)
{
if(Pow[i] == n)
{
break;
}
}
in = f(i,m);
printf("%d %d\n",in.a,in.b);
}
}
G. Rectilinear Regions
H. Rock Paper Scissors
题解:FFT,把s1串中石头剪刀布的位置记录下来,再把S2串中石头剪刀布的位置记录下来。分输赢做三次FFT。
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define maxn (1<<18)
#define pi 3.141592653589793238462643383
using namespace std; struct complex
{
double re,im;
complex(double r=0.0,double i=0.0) {re=r,im=i;}
void print() {printf("%.lf ",re);}
} a[maxn*],b[maxn*],W[][maxn*]; int N,na,nb,rev[maxn*],n,m;
char s1[],s2[];
double c[maxn*],ans;
complex operator +(const complex&A,const complex&B) {return complex(A.re+B.re,A.im+B.im);}
complex operator -(const complex&A,const complex&B) {return complex(A.re-B.re,A.im-B.im);}
complex operator *(const complex&A,const complex&B) {return complex(A.re*B.re-A.im*B.im,A.re*B.im+A.im*B.re);} void FFT(complex*a,int f)
{
complex x,y;
for (int i=; i<N; i++) if (i<rev[i]) swap(a[i],a[rev[i]]);
for (int i=; i<N; i<<=)
for (int j=,t=N/(i<<); j<N; j+=i<<)
for (int k=,l=; k<i; k++,l+=t) x=W[f][l]*a[j+k+i],y=a[j+k],a[j+k]=y+x,a[j+k+i]=y-x;
if (f) for (int i=; i<N; i++) a[i].re/=N;
} void work()
{
for (int i=; i<N; i++)
{
int x=i,y=;
for (int k=; k<N; x>>=,k<<=) (y<<=)|=x&;
rev[i]=y;
}
for (int i=; i<N; i++) W[][i]=W[][i]=complex(cos(*pi*i/N),sin(*pi*i/N)),W[][i].im=-W[][i].im;
}
void doit()
{
work(),FFT(a,),FFT(b,);
for (int i=; i<N; i++) a[i]=a[i]*b[i];
FFT(a,);
for (int i=; i<na+nb-; i++)
{
c[i]+=a[i].re;
if(i>=m-) ans=max(ans,c[i]);
//printf("%d %d\n",i,c[i]);
}
} void popo()
{
scanf("%d%d",&n,&m);
scanf("%s",s1);
scanf("%s",s2);
memset(a,,sizeof(a));
memset(b,,sizeof(b));
na=n;nb=m;
for(int i=;i<n;i++)
if(s1[i]=='R') a[i].re=;
for(int i=;i<m;i++)
if(s2[i]=='P') b[m-i-].re=;
for (N=; N<na||N<nb; N<<=); N<<=;
doit();
//printf("------\n");
memset(a,,sizeof(a));
memset(b,,sizeof(b));
for(int i=;i<n;i++)
if(s1[i]=='P') a[i].re=;
for(int i=;i<m;i++)
if(s2[i]=='S') b[m-i-].re=;
for (N=; N<na||N<nb; N<<=); N<<=;
doit();
//printf("------\n");
memset(a,,sizeof(a));
memset(b,,sizeof(b));
for(int i=;i<n;i++)
if(s1[i]=='S') a[i].re=;
for(int i=;i<m;i++)
if(s2[i]=='R') b[m-i-].re=;
for (N=; N<na||N<nb; N<<=); N<<=;
doit();
} int main()
{
popo();
printf("%.lf\n",ans);
}
I. Slot Machines
补题kk
我们把这个数组倒过来,现在变成了我们要去掉末尾的一段,使得前面部分循环,并且不完整的循环节在数列的前方。对于两段循环来说,开头一部分肯定是一样的(否则怎么能叫循环呢),如果有一段循环不完整,那么开头一部分肯定是一样的,而这里循环的开头就是倒过来的数组的前缀,后面是一个完整的数组,前缀和后缀相同,我们想到了什么呢?kmp!
但是这里我们只需要$fail$就可以了。
先对倒过来的数组$fail$一遍,得到$f$数组,然后循环长度就变成了$i-f[i]$,对此我们稍微证明一下为什么。
对于$i-f[i]>=f[i]$,也就是相等的前缀和后缀不重叠,那么这必然是一个循环长度。
对于$i-f[i]<f[i]$,也就是相等的前缀喝后缀是重叠的,那么我们就要稍微理解一下,设$len=i-f[i]$那么必然有$s{f[i]->f[i]+len]}==s{f[i]-len->f[i]}$,然后一步一步的画过来,这个也是循环节(这部分还是画图好理解些)
#include<bits/stdc++.h>
#define clr(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const int maxn=;
int n;
int a[maxn],f[maxn];
void fail(){
f[]=-;
for(int j=;j<n;j++)
{
for(int i=f[j-];;i=f[i])
{
if(a[j]==a[i+]){
f[j]=i+;
break;
}else if(i==-)
{
f[j]=-;
break;
}
}
}
}
int main(){
while(cin>>n)
{
for(int i=n-;i>=;i--)
{
scanf("%d",&a[i]);
}
fail();
int k=n,p=;
for(int i=;i<n;i++)
{
int kk=n-i-;
int pp=i-f[i];
if(kk+pp<k+p){
k=kk,p=pp;
}else if(kk+pp==k+p&&pp<p){
k=kk,p=pp;
}
}
printf("%d %d\n",k,p); }
}
J. Strongly Matchable
K. Untangling Chain
L. Vacation Plans
2017-2018 ACM-ICPC, Asia Daejeon Regional Contest的更多相关文章
- ACM ICPC Central Europe Regional Contest 2013 Jagiellonian University Kraków
ACM ICPC Central Europe Regional Contest 2013 Jagiellonian University Kraków Problem A: Rubik’s Rect ...
- 2019-2020 ICPC, Asia Jakarta Regional Contest (Online Mirror, ICPC Rules, Teams Preferred)
2019-2020 ICPC, Asia Jakarta Regional Contest (Online Mirror, ICPC Rules, Teams Preferred) easy: ACE ...
- 2017-2018 ACM-ICPC, Asia Daejeon Regional Contest PART(10/12)
$$2017-2018\ ACM-ICPC,\ Asia\ Daejeon\ Regional\ Contest$$ \(A.Broadcast\ Stations\) \(B.Connect3\) ...
- 2018-2019, ICPC, Asia Yokohama Regional Contest 2018 K
传送门:https://codeforces.com/gym/102082/attachments 题解: 代码: /** * ┏┓ ┏┓ * ┏┛┗━━━━━━━┛┗━━━┓ * ┃ ┃ * ┃ ━ ...
- 2018 ICPC Asia Jakarta Regional Contest
题目传送门 题号 A B C D E F G H I J K L 状态 Ο . . Ο . . Ø Ø Ø Ø . Ο Ο:当场 Ø:已补 . : 待补 A. Edit Distance Thin ...
- Gym - 101981K The 2018 ICPC Asia Nanjing Regional Contest K.Kangaroo Puzzle 暴力或随机
题面 题意:给你1个20*20的格子图,有的是障碍有的是怪,你可以每次指定上下左右的方向,然后所有怪都会向那个方向走, 如果2个怪撞上了,就融合在一起,让你给不超过5w步,让所有怪都融合 题解:我们可 ...
- Gym - 101981M The 2018 ICPC Asia Nanjing Regional Contest M.Mediocre String Problem Manacher+扩增KMP
题面 题意:给你2个串(长度1e6),在第一个串里找“s1s2s3”,第二个串里找“s4”,拼接后,是一个回文串,求方案数 题解:知道s1和s4回文,s2和s3回文,所以我们枚举s1的右端点,s1的长 ...
- Gym - 101981G The 2018 ICPC Asia Nanjing Regional Contest G.Pyramid 找规律
题面 题意:数一个n阶三角形中,有多少个全等三角形,n<=1e9 题解:拿到题想找规律,手画开始一直数漏....,最后还是打了个表 (打表就是随便定个点为(0,0),然后(2,0),(4,0), ...
- Gym - 101981I The 2018 ICPC Asia Nanjing Regional Contest I.Magic Potion 最大流
题面 题意:n个英雄,m个怪兽,第i个英雄可以打第i个集合里的一个怪兽,一个怪兽可以在多个集合里,有k瓶药水,每个英雄最多喝一次,可以多打一只怪兽,求最多打多少只 n,m,k<=500 题解:显 ...
- Gym - 101981D The 2018 ICPC Asia Nanjing Regional Contest D.Country Meow 最小球覆盖
题面 题意:给你100个三维空间里的点,让你求一个点,使得他到所有点距离最大的值最小,也就是让你找一个最小的球覆盖掉这n个点 题解:红书模板题,这题也因为数据小,精度也不高,所以也可以用随机算法,模拟 ...
随机推荐
- p4042 [AHOI2014/JSOI2014]骑士游戏
传送门 分析 我们发现对于一个怪物要不然用魔法代价使其无需考虑后续点要么用普通攻击使其转移到他所连的所有点上且所有边大于0 所以我们可以先将一个点的最优代价设为魔法攻击的代价 之后我们倒着跑spfa求 ...
- Ubuntu14.04 下安装Samba服务
1.更改linux镜像源: # vim /etc/apt/sources.list deb http://mirrors.163.com/ubuntu/ trusty main restricted ...
- (I/O流)在100ms内桌面上生成一个200M大小的文件
最终速度取决于硬盘的读写速度 package com.laurdawn; import java.io.File; import java.io.FileInputStream; import jav ...
- HttpUploader6-queue版本更新说明
HttpUploader6-queue版本更新说明 博客园:http://www.cnblogs.com/xproer/p/5109761.html 网易博客:http://hyhyo.blog.16 ...
- 浅谈tcp_nodelay的作用
今天在用nginx作web缓存的时候,发现在http里加入这样个参数,能有效的提高数据的实时响应性,那就是tcp_nodelay.下面我们来说说tcp_nodelay的原理: TCP_NODELAY和 ...
- 深入理解java虚拟机(七)类加载的时机
Class 文件中描述的各种信息都必须加载到虚拟机中才能运行和使用.而虚拟机怎么加载这些Class 文件呢?Class 文件进入到虚拟机中会发生什么变化呢? 虚拟机类加载机制是指 虚拟机把描述类的数据 ...
- PyCharm社区版+Django搭建web开发环境-1
PyCharm开源社区版不像商业版那样可以直接通过Django来创建项目,必须通过以下几个步骤进行: 1. 创建项目:在cmd命令行下输入:django-admin startproject Demo ...
- Reporting Service服务SharePoint集成模式安装配置(5、安装 SQL SERVER 2012 SP1产品)
有过SQL2012 数据库安装经验的,可以跳过这一步骤直接进入第五步骤:RS外接程序的安装 数据库安装工具:SQLServer2012 SP1 Name:SQLServer2012SP1-FullS ...
- EF修改model自动更新数据库
最近用MVC+EF学习时遇到修改model后而数据库没更新报错,就在网上找关于数据迁移自动更新数据库的,折腾了大半天终于弄了出来 第一步:在程序包管理器控制台里: Enable-Migrations ...
- Web.config配置文件详解(新手必看) (转载)
原文地址:http://www.cnblogs.com/gaoweipeng/archive/2009/05/17/1458762.html <?xmlversion="1.0&quo ...