Gym-101653:acific Northwest Regional Contest (2019训练第一场)
本套题没有什么数据结构题,图论题,唯一有价值的就是Q题博弈,在最后面,读者可以直接拉到最下面。
(还剩下两个,估计每什么价值的题,懒得补了
M .Polyhedra
pro:欧拉公式,V-E+F=2;给定V,E,求F
sol:F=E-V+2;
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=;
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
int a, b;
scanf("%d%d", &a, &b);
printf("%d\n", b - a + );
}
return ;
}
N .Majority
pro: 给定一些一些1到1000的数字,问最小的出现次数最多的数字。
sol: 模拟。
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=;
int num[maxn];
int main()
{
int T,N,x;
scanf("%d",&T);
while(T--){
scanf("%d",&N);
rep(i,,) num[i]=;
rep(i,,N){
scanf("%d",&x);
num[x]++;
}
int ans=,x=-;
rep(i,,) {
if(num[i]>x) ans=i,x=num[i];
}
printf("%d\n",ans);
}
return ;
}
O .Diamonds
pro:给定一些二元组,求最长的序列,满足a递增,b递减。
sol:N^2暴力即可。
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=;
struct in{
double x,y;
}s[maxn];
int dp[];
int main()
{
int T,N,ans;
scanf("%d",&T);
while(T--){
scanf("%d",&N); ans=;
rep(i,,N) scanf("%lf%lf",&s[i].x,&s[i].y);
rep(i,,N){
dp[i]=;
rep(j,,i-){
if(s[j].x<s[i].x&&s[j].y>s[i].y) dp[i]=max(dp[i],dp[j]+);
}
ans=max(ans,dp[i]);
}
printf("%d\n",ans);
}
return ;
}
R .Ramp Number
pro:一个数字X是合法的,当且仅当各位数字从左到右不降。 如果一个数字的合法,求多少个小于他的数是合法的。
sol:基本数位DP。
#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=;
ll dp[maxn][]; char c[maxn]; int a[maxn],len;
ll dfs(int pos,int lim,int now)
{
if(pos==len) return ;
if(!lim&&dp[pos][now]) return dp[pos][now];
ll res=; int up=; if(lim) up=a[pos+];
rep(j,now,up) res+=dfs(pos+,lim&&j==a[pos+],j);
return dp[pos][now]=res;
}
void solve()
{
ll res=;
rep(i,,len){
memset(dp,,sizeof(dp));
int up=; if(i==) up=a[];
rep(j,,up) res+=dfs(i,i==&&j==up,j);
}
printf("%lld\n",res);
}
int main()
{
int T;
scanf("%d",&T);
while(T--){
scanf("%s",c+);
len=strlen(c+);
rep(i,,len) a[i]=c[i]-'';
bool F=true;
rep(i,,len) if(a[i]<a[i-]) F=false;
if(!F){ puts("-1"); continue;}
solve();
}
return ;
}
X .Wrench
pro:把一个带小数的数字表示为整数 加一个 分数形式,满足分母是2的幂次,而且要越小的满足的,允许有最后一位的误差。
sol:模拟,细节需要注意。
#include<bits/stdc++.h>
using namespace std;
int t,n;
char s[],s1[];
int main(){
for(scanf("%d",&t);t--;){
scanf("%s",s);n=strlen(s);
int p=;bool flag=,flag1=;
while(s[p]==''&&p<n)p++;
while(s[p]!='.'&&p<n)putchar(s[p++]),flag1=;
for(int i=p+;i<n;i++)
if(s[i]!=''){flag=;break;}
if(flag){if(flag1)putchar(' ');}
else{puts("\"");continue;}
flag=;
for(int i=;i<=;i<<=){
for(int j=;j<i;j++){
double x=1.0*j/i;
for(int v=;v<;v++)x*=,s1[v]=(int)x%+'';
bool f=;
for(int k=;p+k<n;k++)
if(s1[k-]!=s[p+k]&&(p+k<n-||s1[k-]+!=s[p+k])){f=;break;}
if(f){printf("%d/%d\"\n",j,i);flag=;break;}
}
if(flag)break;
}
}
return ;
}
U .Top 25
题意:给定A和B,分别是不同的1到N的排列,找到连续的段(越短越好),代表的集合相同。
思路:每次找到对应的位置,如果最远的对应位置和当前相同,说明这段集合相同。
Map+clear: 3525ms
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=;
map<string, int>Map;
int f[maxn];
vector<int>ans;
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
int N,x,y;
Map.clear();
string s;
scanf("%d",&N);
rep(i,,N){
cin>>s;
Map[s]=i;
}
rep(i,,N){
cin >> s;
f[Map[s]] = i;
}
rep(i,,N){
if(i==f[i]) printf("1 ");
else{
int maxx = f[i];
for(int j = i + ; j <= maxx; j++){
if(f[j] > maxx)maxx = f[j];
}
printf("%d ",maxx-i+);
i = maxx;
}
}
puts("");
}
return ;
}
Map: 4227ms
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=;
map<string, int>Map;
int f[maxn];
vector<int>ans;
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
int N,x,y;
string s;
scanf("%d",&N);
rep(i,,N){
cin>>s;
Map[s]=i;
}
rep(i,,N){
cin >> s;
f[Map[s]] = i;
}
rep(i,,N){
if(i==f[i]) printf("1 ");
else{
int maxx = f[i];
for(int j = i + ; j <= maxx; j++){
if(f[j] > maxx)maxx = f[j];
}
printf("%d ",maxx-i+);
i = maxx;
}
}
puts("");
}
return ;
}
unordered_map:2479ms
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=;
unordered_map<string, int>Map;
int f[maxn];
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
Map.clear();
int N,x,y;
string s;
scanf("%d",&N);
rep(i,,N){
cin>>s;
Map[s]=i;
}
rep(i,,N){
cin >> s;
f[Map[s]] = i;
}
rep(i,,N){
if(i==f[i]) printf("1 ");
else{
int maxx = f[i];
for(int j = i + ; j <= maxx; j++){
if(f[j] > maxx)maxx = f[j];
}
printf("%d ",maxx-i+);
i = maxx;
}
}
puts("");
}
return ;
}
这告诉我们map的效率和map的大小有关,所以要及时的clear。 而我如果用set,一位set一直在erase,元素会慢慢表少,所以二分的速度会更快。
set: 3010ms
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=;
set<string>s;
string a[maxn],b[maxn];
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
int N,x,y,tot=;
scanf("%d",&N);
rep(i,,N) cin>>a[i];
rep(i,,N) cin>>b[i];
rep(i,,N) {
tot++;
if(s.find(a[i])!=s.end()) s.erase(a[i]);
else s.insert(a[i]);
if(s.find(b[i])!=s.end()) s.erase(b[i]);
else s.insert(b[i]);
if(s.empty()) {
printf("%d ",tot);
tot=;
}
}
puts("");
}
return ;
}
(但是主要的时间还是在输入输出那里。
W .Wormhole
pro:给定三维的N个点,有一些点对可以互通,其他的点对距离是欧几里得距离。Q次询问点对最近距离。
sol:folyd。
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=;
typedef long long ll;
struct node
{
double x, y, z;
double operator - (const node& a)const
{
return (sqrt((x - a.x) * (x - a.x) + (y - a.y) * (y - a.y) + (z - a.z) * (z - a.z)));
}
}a[maxn];
map<string, int>Map;
double dis[][];
int main()
{
int T, cases = ;
scanf("%d", &T);
while(T--)
{
memset(dis, , sizeof(dis));
Map.clear();
int n, m;
scanf("%d", &n);
string s, s1;
for(int i = ; i <= n; i++)
{
cin >> s >> a[i].x >> a[i].y >> a[i].z;
Map[s] = i;
}
for(int i = ; i <= n; i++)
{
for(int j = i + ; j <= n; j++)
{
dis[i][j] = dis[j][i] = a[i] - a[j];
//cout<<dis[i][j]<<endl;
}
}
cin >> m;
while(m--)
{
cin >> s >> s1;
dis[Map[s]][Map[s1]] = ;
}
for(int k = ; k <= n; k++)
for(int i = ; i <= n; i++)
for(int j = ; j <= n; j++)
dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
cin >> m;
cout<<"Case "<<++cases<<":\n";
while(m--)
{
cin >> s >> s1;
cout<<"The distance from "<<s<<" to "<<s1<<" is "<<(ll)(dis[Map[s]][Map[s1]]+0.5)<<" parsecs.\n";
}
}
return ;
}
V .Towers
pro:给定N,让填数独,然后给出(N+2)*(N+2)的矩阵,里面N*N的数字或者未知,周围4行表示从那个方向看过去的LIS。N<=5
sol:搜索,需要及时减枝。 check函数就是给个方向的判定。 只跑了30ms,估计包本来就可以暴力一点,即到了边界再减枝?
减枝1:对于每填一个数,就看和上面的数字是否有重复。
减枝2:对于每个数,看左边和上边看过去的LIS已经超过题目描述,退出。
判定3:对于右边界和下边界,检查从右和下看过去的LIS。
#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=;
char c[][],ans[][];
int vis[][],N;
int get(int x,int y,int tx,int ty,int X,int Y)
{
int res=,now=;
while(){
x+=tx; y+=ty;
if(ans[x][y]>now) now=ans[x][y],res++;
if(x==X&&y==Y) return res;
}
return res;
}
bool check(int u,int v)
{
rep(i,,u-) if(ans[u][v]==ans[i][v]) return false;
if(c[u][]!='-'){
int t=get(u,,,,u,v);
if(t>c[u][]-'') return false;
if(v==N&&t!=c[u][]-'') return false;
}
if(c[][v]!='-'){
int t=get(,v,,,u,v);
if(t>c[][v]-'') return false;
if(u==N&&t!=c[][v]-'') return false;
}
if(v==N&&c[u][N+]!='-'){
if(get(u,N+,,-,u,)!=c[u][N+]-'') return false;
}
if(u==N&&c[N+][v]!='-'){
if(get(N+,v,-,,,v)!=c[N+][v]-'') return false;
}
return true;
}
bool dfs(int u,int v)
{
if(u==N+&&v==) {
return true;
}
int L=,R=N;
if(c[u][v]!='-') L=R=c[u][v]-'';
rep(i,L,R){
if(!vis[u][i]){
vis[u][i]=; ans[u][v]=i;
if(v<N){
if(check(u,v)){
if(dfs(u,v+)) return true;
}
}
else{
if(check(u,v))
{
if(dfs(u+,)) return true;
}
}
vis[u][i]=;
}
}
return false;
}
int main()
{
int T;
scanf("%d",&T);
while(T--){
scanf("%d",&N);
memset(vis,,sizeof(vis));
rep(i,,N+) scanf("%s",c[i]);
if(!dfs(,)) puts("no\n");
else {
rep(i,,N) {
rep(j,,N) putchar(ans[i][j]+'');
puts("");
}
puts("");
}
}
return ;
}
T .Runes
pro:给定等式,其中有不超过6个问号,让你填一个相同的未出现过的数字,使等式满足。
sol:枚举。注意负号,0等情况。
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=;
typedef long long ll;
bool judge(char s[], int x, ll& y)
{
int n = strlen(s);
char s1[];
memcpy(s1, s, sizeof(s1));
for(int i = ; i < n; i++)
{
if(s1[i] == '?')s1[i] = '' + x;
}
if(s1[] == '-' && s1[] == '')return false;
if(s1[] == '' && n != )return false;
bool flag;
if(s1[] == '-')flag = ;
else flag = ;
y = ;
for(int i = flag; i < n; i++)y = y * + s1[i] - '';
if(flag)y = -y;
}
char s[], s1[], s2[], s3[];
int vis[];
int main()
{
int T, cases = ;
scanf("%d", &T);
while(T--)
{
memset(s1, , sizeof(s1));
memset(s2, , sizeof(s2));
memset(s3, , sizeof(s3));
memset(vis, , sizeof(vis));
scanf("%s", s);
int n = strlen(s), tmp, tmp1;
for(int i = ; i < n; i++)
{
if((isdigit(s[i]) || s[i] == '?') && (s[i + ] == '+' || s[i + ] == '-' || s[i + ] == '*'))
{
tmp = i + ;
break;
}
}
for(int i = ; i < n; i++)if(s[i] == '='){tmp1 = i;break;}
for(int i = ; i < n; i++)if(isdigit(s[i]))vis[s[i] - ''] = ;
for(int i = ; i < tmp; i++)s1[i] = s[i];
for(int i = tmp + , j = ; i < tmp1; i++, j++)s2[j] = s[i];
for(int i = tmp1 + , j = ; i < n; i++, j++)s3[j] = s[i];
bool ok = ;
for(int i = ; i <= ; i++)
{
if(vis[i])continue;
ll a, b, c;
bool flag = ;
if(judge(s1, i, a) && judge(s2, i, b) && judge(s3, i, c))
{
if(s[tmp] == '-' && a - b == c)flag = ;
if(s[tmp] == '+' && a + b == c)flag = ;
if(s[tmp] == '*' && a * b == c)flag = ;
}
if(flag)
{
ok = ;
printf("%d\n", i);
break;
}
}
if(!ok)printf("-1\n");
}
return ;
}
Q .Number Game
pro:双人博弈,给定一个N的排列,Alice先手,Bob后手,他们轮流取,取到数字1的胜,能取走一个数字的条件是两旁没有比它大的数字。
sol:我们发现,只有和1相邻的连续区间是要考虑的; 之外的区间因为一定可以按一定顺序取完,所以只考虑奇偶性。
即用dp[L][R][k]保存先手的情况:[L,R]是当前包含数字1的区间,k是此区间外的未取的个数奇偶性。然后就可以记忆化搜索了。
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=;
int dp[maxn][maxn][],a[maxn],pos;
int dfs(int L,int R,int k)
{
if(L==R) return ;
if(dp[L][R][k]!=-)
return dp[L][R][k];
if(k==&&!dfs(L,R,)) dp[L][R][k]=;
rep(i,L,R){
bool F=true;
if(i->=L&&a[i-]>a[i]) F=false;
if(i+<=R&&a[i+]>a[i]) F=false;
if(!F) continue;
if(i==pos) dp[L][R][k]=;
else {
if(i<pos){
if(!dfs(i+,R,(k+i-L)&)) dp[L][R][k]=;
}
else {
if(!dfs(L,i-,(k+R-i)&)) dp[L][R][k]=;
}
}
}
if(dp[L][R][k]==-) dp[L][R][k]=;
return dp[L][R][k];
}
int main()
{
int N,T;
scanf("%d",&T);
while(T--){
scanf("%d",&N);
rep(i,,N){
scanf("%d",&a[i]);
if(a[i]==) pos=i;
}
memset(dp,-,sizeof(dp));
dfs(,N,);
if(dp[][N][]) puts("Alice");
else puts("Bob");
}
return ;
}
Gym-101653:acific Northwest Regional Contest (2019训练第一场)的更多相关文章
- 2020.5.4-ICPC Pacific Northwest Regional Contest 2019
A. Radio Prize All boring tree-shaped lands are alike, while all exciting tree-shaped lands are exci ...
- 2018-2019 ACM-ICPC Pacific Northwest Regional Contest (Div. 1)
2018-2019 ACM-ICPC Pacific Northwest Regional Contest (Div. 1) 思路: A Exam 思路:水题 代码: #include<bits ...
- 2018 ICPC Pacific Northwest Regional Contest I-Inversions 题解
题目链接: 2018 ICPC Pacific Northwest Regional Contest - I-Inversions 题意 给出一个长度为\(n\)的序列,其中的数字介于0-k之间,为0 ...
- Gym 101655:2013Pacific Northwest Regional Contest(寒假自训第13场)
A .Assignments 题意:给定距离D,以及N个飞机的速度Vi,单位时间耗油量Fi,总油量Ci.问有多少飞机可以到达目的地. 思路:即问多少飞机满足(Ci/Fi)*Vi>=D ---- ...
- Gym - 101615J Grid Coloring DP 2017-2018 ACM-ICPC Pacific Northwest Regional Contest (Div. 1)
题目传送门 题目大意: 给出n*m的网格,有红蓝两种颜色,每个格子都必须被染色,当一个格子被染成蓝色后,这个格子左上方的一块都必须被染成蓝色,问最后的方案数量. 思路: 按照题目条件,如果有一个格子被 ...
- Gym - 101982A 2018-2019 ACM-ICPC Pacific Northwest Regional Contest (Div. 1) A. Exam
题面 题意:你和朋友一起做了n道判断题,现在你知道你们两的答案,也知道你朋友对了k个,问你至少对了几个 题解:假设你和朋友n个答案都一样,那你是不是也对了k个,假设你和朋友有1个答案不一样,是不是,你 ...
- Gym - 101982B 2018-2019 ACM-ICPC Pacific Northwest Regional Contest (Div. 1) B. Coprime Integers Mobius+容斥 ab间gcd(x,y)=1的对数
题面 题意:给你 abcd(1e7),求a<=x<=b,c<=y<=d的,gcd(x,y)=1的数量 题解:经典题目,求从1的到n中选x,从1到m中选y的,gcd(x,y)=k ...
- 2015-2016 ACM-ICPC Pacific Northwest Regional Contest (Div. 2) S Surf
SurfNow that you've come to Florida and taken up surng, you love it! Of course, you've realized that ...
- Contest Setting 2018 ICPC Pacific Northwest Regional Contest dp
题目:https://vj.69fa.cn/12703be72f729288b4cced17e2501850?v=1552995458 dp这个题目网上说是dp+离散化这个题目要对这些数字先处理然后进 ...
随机推荐
- 最新jquery+easyui_api培训文档
目 录 1 Accordion(可折叠标签) 2 1.1 实例 2 1.2 参数 3 2 DateBox(日期框) 4 2.1 实例 4 2.2 参数 6 2.3 事件 6 2.4 方法 6 3 C ...
- Ubuntu云服务器下mysql授权远程登陆
1)首先以 root 帐户登陆 MySQL(在授权之前要确保3306端口开放)2)创建远程登陆用户并授权 > grant all PRIVILEGES on discuz.* to zhan@' ...
- shell脚本分析一
Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁.Shell 既是一种命令语言,又是一种程序设计语言.Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界 ...
- day1-python简介+安装
Python 简介 Python 是一个高层次的结合了解释性.编译性.互动性和面向对象的脚本语言. Python 的设计具有很强的可读性,相比其他语言经常使用英文关键字,其他语言的一些标点符号,它具有 ...
- information_schema
views 视图表,查看当前数据库有哪些视图 select table_catalog,table_schema,table_name,is_updatable,definer,security_ty ...
- Cracking The Coding Interview 4.0_二叉树
#include <iostream> #include <string> using namespace std; class tree { public: tree() { ...
- 深入理解java虚拟机---JDK8-废弃永久代(PermGen)迎来元空间(Metaspace)(十二)
引用:https://www.cnblogs.com/yulei126/p/6777323.html JDK8-废弃永久代(PermGen)迎来元空间(Metaspace) 1.背景 2.为什么废 ...
- calc()
width:calc(): cale(a)计算出表达式a的值. e.g: height:cale(100vh-200px):vh,是指CSS中相对长度单位,表示相对视口高度,通常视口长度单位会被分成1 ...
- ThreadPoolExcutor
先保存一个链接,后续更新 JAVA进阶----ThreadPoolExecutor机制 ExecutorService生命周期 理解ThreadPoolExecutor源码(一)线程池的corePoo ...
- web项目与jsp有关的三个jar的依赖
<!-- jsp --> <dependency> <groupId>javax.servlet</groupId> <artifactId> ...