本套题没有什么数据结构题,图论题,唯一有价值的就是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. redis使用epoll

    redis使用epoll的代码在ae_epoll.c文件中. epoll_create:redis服务器在启动时,创建事件循环,调用epoll_create方法创建epoll实例. static in ...

  2. 谈一谈JUnit神奇的报错 java.lang.Exception:No tests found matching

    最近在学习Spring+SpringMVC+MyBatis,一个人的挖掘过程确实有点艰难,尤其是有一些神奇的报错让你会很蛋疼.特别是接触一些框架还是最新版本的时候,会因为版本问题出现很多错误,欢迎大家 ...

  3. 如何将两个字段合成一个字段显示(oracle和sqlserver的区别)

    oracle中,如何将两个字段数据合并成一个字段显示,接下来看一下在sql server和pl/sql的区别 sql server中如何合并(用Cast()函数) --1.创建模拟的数据表--- cr ...

  4. 六招让你的Ubuntu马上提速

    Chris Hoffman Ubuntu的启动速度非常快,按了开机键之后很快就进入桌面.但我们仍然可以充分利用内存,通过多种方法让开机速度更快.某些方法真的可以提速,对于旧电脑的效果尤其明显. 选用轻 ...

  5. 各种形式的熵函数,KL距离

    自信息量I(x)=-log(p(x)),其他依次类推. 离散变量x的熵H(x)=E(I(x))=-$\sum\limits_{x}{p(x)lnp(x)}$ 连续变量x的微分熵H(x)=E(I(x)) ...

  6. Win10系列:VC++绘制文本

    20.7.2小节介绍了如何使用Direct2D在应用窗口中绘制图片,本小节将基于20.7.2小节的项目进一步介绍如何实现文本的绘制.打开D2DBasicAnimation.h头文件,并在D2DBasi ...

  7. learning at command AT+CIMI

    AT command AT+CIMI [Purpose]        Learning how to get the International Mobile Subscriber Identity ...

  8. owin启动事项

    在上下文中找不到 owin.Environment 项 owin没有启动. 尝试加载应用时出现了以下错误.- 找不到包含 OwinStartupAttribute 的程序集 startup类不是通过v ...

  9. U深度U盘启动盘制作教程

    ① 下载u深度u盘启动盘制作工具 ② 一个能够正常使用的u盘(容量大小建议在4g以上) 第一步:安装u深度u盘启动盘制作工具 双击打开已下载好的安装包,点击窗口中立即安装即可: 等待安装完成后,可以点 ...

  10. bzoj1239

    题解: 首先计算出两两之间的距离 然后二分答案 然后贪心判断是否可以放置少于等于k个 代码: #include<bits/stdc++.h> using namespace std; ; ...