本套题没有什么数据结构题,图论题,唯一有价值的就是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训练第一场)的更多相关文章

  1. 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 ...

  2. 2018-2019 ACM-ICPC Pacific Northwest Regional Contest (Div. 1)

    2018-2019 ACM-ICPC Pacific Northwest Regional Contest (Div. 1) 思路: A Exam 思路:水题 代码: #include<bits ...

  3. 2018 ICPC Pacific Northwest Regional Contest I-Inversions 题解

    题目链接: 2018 ICPC Pacific Northwest Regional Contest - I-Inversions 题意 给出一个长度为\(n\)的序列,其中的数字介于0-k之间,为0 ...

  4. Gym 101655:2013Pacific Northwest Regional Contest(寒假自训第13场)

    A .Assignments 题意:给定距离D,以及N个飞机的速度Vi,单位时间耗油量Fi,总油量Ci.问有多少飞机可以到达目的地. 思路:即问多少飞机满足(Ci/Fi)*Vi>=D  ---- ...

  5. Gym - 101615J Grid Coloring DP 2017-2018 ACM-ICPC Pacific Northwest Regional Contest (Div. 1)

    题目传送门 题目大意: 给出n*m的网格,有红蓝两种颜色,每个格子都必须被染色,当一个格子被染成蓝色后,这个格子左上方的一块都必须被染成蓝色,问最后的方案数量. 思路: 按照题目条件,如果有一个格子被 ...

  6. Gym - 101982A 2018-2019 ACM-ICPC Pacific Northwest Regional Contest (Div. 1) A. Exam

    题面 题意:你和朋友一起做了n道判断题,现在你知道你们两的答案,也知道你朋友对了k个,问你至少对了几个 题解:假设你和朋友n个答案都一样,那你是不是也对了k个,假设你和朋友有1个答案不一样,是不是,你 ...

  7. 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 ...

  8. 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 ...

  9. Contest Setting 2018 ICPC Pacific Northwest Regional Contest dp

    题目:https://vj.69fa.cn/12703be72f729288b4cced17e2501850?v=1552995458 dp这个题目网上说是dp+离散化这个题目要对这些数字先处理然后进 ...

随机推荐

  1. 最新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 ...

  2. Ubuntu云服务器下mysql授权远程登陆

    1)首先以 root 帐户登陆 MySQL(在授权之前要确保3306端口开放)2)创建远程登陆用户并授权 > grant all PRIVILEGES on discuz.* to zhan@' ...

  3. shell脚本分析一

    Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁.Shell 既是一种命令语言,又是一种程序设计语言.Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界 ...

  4. day1-python简介+安装

    Python 简介 Python 是一个高层次的结合了解释性.编译性.互动性和面向对象的脚本语言. Python 的设计具有很强的可读性,相比其他语言经常使用英文关键字,其他语言的一些标点符号,它具有 ...

  5. information_schema

    views 视图表,查看当前数据库有哪些视图 select table_catalog,table_schema,table_name,is_updatable,definer,security_ty ...

  6. Cracking The Coding Interview 4.0_二叉树

    #include <iostream> #include <string> using namespace std; class tree { public: tree() { ...

  7. 深入理解java虚拟机---JDK8-废弃永久代(PermGen)迎来元空间(Metaspace)(十二)

    引用:https://www.cnblogs.com/yulei126/p/6777323.html JDK8-废弃永久代(PermGen)迎来元空间(Metaspace)   1.背景 2.为什么废 ...

  8. calc()

    width:calc(): cale(a)计算出表达式a的值. e.g: height:cale(100vh-200px):vh,是指CSS中相对长度单位,表示相对视口高度,通常视口长度单位会被分成1 ...

  9. ThreadPoolExcutor

    先保存一个链接,后续更新 JAVA进阶----ThreadPoolExecutor机制 ExecutorService生命周期 理解ThreadPoolExecutor源码(一)线程池的corePoo ...

  10. web项目与jsp有关的三个jar的依赖

    <!-- jsp --> <dependency> <groupId>javax.servlet</groupId> <artifactId> ...