T1小凯的疑惑

小凯手中有两种面值的金币,两种面值均为正整数且彼此互素。每种金币小凯都有 无数个。在不找零的情况下,仅凭这两种金币,有些物品他是无法准确支付的。现在小 凯想知道在无法准确支付的物品中,最贵的价值是多少金币?注意:输入数据保证存在 小凯无法准确支付的商品。

Solution

2017数论题,感觉是历史以来最难的一道。

对于ax+by=c(a>=0,b>=0)当方程无解是,必定为x<0&&y>0且下一组解x>0&&y<0那x为-1,y为a-1,那c就是a*b-a-b。

Code

#include<iostream>
#include<algorithm>
using namespace std;
long long a,b;
int main()
{
cin>>a>>b;
cout<<a*b-a-b;
}

T2时间复杂度

题面太长不粘了

模拟题,注意细节。。

Code

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int t,vis[],tag,tag2,n,ans,num,tot,s[],st[],top,maxx=,yy,zz;
char c,cc[],x,y[],z[];
int main()
{
cin>>t;
while(t--)
{
memset(vis,,sizeof(vis));
scanf("%d",&n);
tag=tag2=tot=num=ans=top=;
cin>>cc;
int p=strlen(cc);
if(cc[]=='n')
for(int j=;j<=p;++j)
if(cc[j]>=''&&cc[j]<='') num=num*+cc[j]-'';
else break;
for(int i=;i<=n;++i)
{
cin>>c;
if(c=='F')
{
cin>>x>>y>>z;
yy=zz=;
if(vis[x])tag=;
vis[x]=;
s[++top]=x;
if(y[]!='n')
{
int o=strlen(y);
for(int k=;k<o;++k)
yy=yy*+y[k]-'';
}
else yy=maxx;
if(z[]!='n')
{
int o=strlen(z);
for(int k=;k<o;++k)
zz=zz*+z[k]-'';
}
else zz=maxx;
if(yy<maxx&&zz==maxx)
{
st[top]=;
tot++;
}
else
if(yy>zz)
{
st[top]=-;
tag2++;
}
else
{
st[top]=;
}
if(!tag2)ans=max(ans,tot);
}
else
{
if(!top)tag=;
if(st[top]==)tot--;
else if(st[top]==-)tag2--;
vis[s[top]]=;
top--;
}
}
if(top||tag)
{
cout<<"ERR\n";
continue;
}
if(ans==num)cout<<"Yes\n";
else cout<<"No\n";
}
return ;
}

T3逛公园

T4奶酪

现有一块大奶酪,它的高度为 hh,它的长度和宽度我们可以认为是无限大的,奶酪 中间有许多 半径相同 的球形空洞。我们可以在这块奶酪中建立空间坐标系,在坐标系中, 奶酪的下表面为z = 0z=0,奶酪的上表面为z = hz=h。

现在,奶酪的下表面有一只小老鼠 Jerry,它知道奶酪中所有空洞的球心所在的坐 标。如果两个空洞相切或是相交,则 Jerry 可以从其中一个空洞跑到另一个空洞,特别 地,如果一个空洞与下表面相切或是相交,Jerry 则可以从奶酪下表面跑进空洞;如果 一个空洞与上表面相切或是相交,Jerry 则可以从空洞跑到奶酪上表面。

位于奶酪下表面的 Jerry 想知道,在 不破坏奶酪 的情况下,能否利用已有的空洞跑 到奶酪的上表面去?

Solution

水题 ,可以把上界和下界都看成一个点,n^2并查集搞一下就可以了。

听说这题爆longlong,反正我开double直接开根,精度没什么问题。

Code

#include<iostream>
#include<cstdio>
#include<cmath>
#define N 1012
using namespace std;
int n,t,f[N];
double h,r;
struct ssd{
double x,y,z;
}a[N];
double calc(int i,int j){
return sqrt((a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y)+(a[i].z-a[j].z)*(a[i].z-a[j].z));
}
int find(int x){return f[x]=f[x]==x?x:find(f[x]);}
int main(){
scanf("%d",&t);
while(t--){
scanf("%d%lf%lf",&n,&h,&r);
for(int i=;i<=n+;++i)f[i]=i;
for(int i=;i<=n;++i){
scanf("%lf%lf%lf",&a[i].x,&a[i].y,&a[i].z);
for(int j=;j<i;++j)
if(calc(i,j)<=r*){
int xx=find(i),yy=find(j);
if(xx!=yy)f[xx]=yy;
}
if(a[i].z-r<=){
int xx=find(i),yy=find();
if(xx!=yy)f[xx]=yy;
}
if(a[i].z+r>=h){
int xx=find(i),yy=find(n+);
if(xx!=yy)f[xx]=yy;
}
}
if(find()==find(n+))printf("Yes\n");
else printf("No\n");
}
return ;
}

T5宝藏

如果我们设dp[s]表示当前选择集合为s时的最小代价,这个状态是有问题的,说不好听点它压根就是错的,因为它压根就没有考虑每个节点的深度。

我们可以这么考虑问题,我们以深度作为阶段,每次从当前选择集合中扩展一些点作为第i层。

这时我们就可以设计状态了,令dp[i][s]表示当前深度做到了i,当前选择集合为s时的最优方案。

转移时可以枚举扩展出哪些点,然后直接转移。

这样的复杂度是3^n*n^2。

但这样太慢,可以利用lowbit等技巧优化常数

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#define N 13
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
int dp[N][<<N],n,m,x,y,l,e[N][N],ji[<<N],f[<<N],b[N],tag[N],be[<<N],ans;
inline int rd(){
int x=;char c=getchar();
while(!isdigit(c))c=getchar();
while(isdigit(c)){
x=(x<<)+(x<<)+(c^);c=getchar();
}
return x;
}
int main(){
n=rd();m=rd();
memset(e,0x3f,sizeof(e));
for(int i=;i<=m;++i){
x=rd();y=rd();l=rd();
e[x][y]=e[y][x]=min(e[x][y],l);
}
memset(dp,0x3f,sizeof(dp));
for(int i=;i<n;++i)ji[<<i]=i,dp[][<<i]=;ans=inf;
ans=min(ans,dp[][(<<n)-]);
for(int i=;i<=n;++i)
for(int s=;s<(<<n);++s){
int top=;
memset(b,0x3f,sizeof(b));
for(int j=;j<=n;++j)if(!(s&(<<j-))){
tag[top]=<<j-;
for(int S=s;S;S-=(S&-S))if(e[j][ji[S&-S]+]!=inf)b[top]=min(b[top],e[j][ji[S&-S]+]*i);
top++;
}
for(int j=;j<(<<top);++j){
f[j]=f[j-(j&-j)]+b[ji[j&-j]];
if(f[j]>=inf)f[j]=inf;
be[j]=be[j-(j&-j)]|tag[ji[j&-j]];
dp[i][s|be[j]]=min(dp[i][s|be[j]],dp[i-][s]+f[j]);
}
ans=min(ans,dp[i][(<<n)-]);
}
printf("%d",ans);
return ;
}

T6列队

Solution

观察到最后一列很特殊,考虑分开维护。

对于每行的前m-1个点开线段树,里面记个size有表示这个位置没人。

那么整体向做移动怎么维护?

其实不用管它,毕竟对于前m-1列只会从后面插入。

那么对于一颗线段树,我们的操作只有从后面插入一个节点,从集合删去一个节点和查找第K个元素。

在最后一列开线段树,操作时分类讨论一下。

注意:n和m不要弄反,初始化size要为m-1不是m!!!

Code

#include<iostream>
#include<cstdio>
#define N 300002
using namespace std;
typedef long long ll;
int size[N],T[N],tot,q;
long long x,y,n,m;
struct node{ll first;bool second;};
struct seg{ll num;int l,r,sum;}tr[N*];
node find(int &cnt,int l,int r,int k){
if(!cnt)cnt=++tot;tr[cnt].sum++;
if(l==r){
if(tr[cnt].num)return node{tr[cnt].num,};
else return node{l,};
}
int mid=(l+r)>>,num=mid-l+-tr[tr[cnt].l].sum;
if(num>=k)return find(tr[cnt].l,l,mid,k);
else return find(tr[cnt].r,mid+,r,k-num);
}
void add(int &cnt,int l,int r,int x,ll y){
if(!cnt)cnt=++tot;
if(l==r){tr[cnt].num=y;return;}
int mid=(l+r)>>;
if(mid>=x)add(tr[cnt].l,l,mid,x,y);
else add(tr[cnt].r,mid+,r,x,y);
}
inline int rd(){
int x=;char c=getchar();while(!isdigit(c))c=getchar();
while(isdigit(c))x=(x<<)+(x<<)+(c^),c=getchar();return x;
}
int main(){
n=rd();m=rd();q=rd();
for(int i=;i<=n;++i)size[i]=m-;//care
size[n+]=n;
for(int i=;i<=q;++i){
x=rd();y=rd();
if(y==m){
node tmp=find(T[n+],,n+q,x);
ll num=tmp.first;
if(tmp.second)num=num*m;
printf("%lld\n",num);
add(T[n+],,n+q,++size[n+],num);
}
else{
node tmp=find(T[x],,m+q,y);
ll num=tmp.first;
if(tmp.second)num=num+(x-)*m;
printf("%lld\n",num);
tmp=find(T[n+],,n+q,x);
ll num2=tmp.first;
if(tmp.second)num2=num2*m;
add(T[x],,m+q,++size[x],num2);
add(T[n+],,n+q,++size[n+],num);
}
}
return ;
}

NOIP2017题解的更多相关文章

  1. NOIP2017 题解

    QAQ--由于没报上名并没能亲自去,自己切一切题聊以慰藉吧-- 可能等到省选的时候我就没有能力再不看题解自己切省选题了--辣鸡HZ毁我青春 D1T1 小凯的疑惑 地球人都会做,懒得写题解了-- D1T ...

  2. [NOIP补坑计划]NOIP2017 题解&做题心得

    终于做完了…… 场上预计得分:?(省一分数线:295) 由于看过部分题解所以没有预计得分qwq 题解: D1T1 小凯的疑惑 题面 震惊!一道小学奥数题竟难倒无数高中考生! 欢迎大家以各种姿势*和谐* ...

  3. NOIP2017 题解(给自己看的) --有坑要填

    目录 D1T1精妙证明: D1T3 D2T2 几道水题就不写了.... D1T1精妙证明: 把ax+by = z 的z按照模a剩余系分类 由于\((a,b)=1\)所以对于每个\(k\in[0, a) ...

  4. 【NOIP题解】NOIP2017 TG D2T3 列队

    列队,NOIP2017 TG D2T3. 树状数组经典题. 题目链接:洛谷. 题意: Sylvia 是一个热爱学习的女孩子. 前段时间,Sylvia 参加了学校的军训.众所周知,军训的时候需要站方阵. ...

  5. NOIP2017 列队 题解报告【56行线段树】

    题目描述 Sylvia 是一个热爱学习的女♂孩子. 前段时间,Sylvia 参加了学校的军训.众所周知,军训的时候需要站方阵. Sylvia 所在的方阵中有n \times mn×m名学生,方阵的行数 ...

  6. noip2017爆炸记——题解&总结&反省(普及组+提高组)

    相关链接: noip2018总结 noip2017是我见过的有史以来最坑爹的一场考试了. 今年北京市考点有一个是我们学校,我还恰好被分到了自己学校(还是自己天天上课的那个教室),于是我同时报了普及提高 ...

  7. 题解[NOIP2017] 列队

    题解[NOIP2017] 列队 题面 解析 看到这题时感觉这个编号很难维护啊? 后来看了lzf大佬的题解才会.. 首先,考虑一个稍微暴力的做法, 维护每一行的前\(m-1\)个人和最后一列的\(n\) ...

  8. 【题解】NOIP2017 提高组 简要题解

    [题解]NOIP2017 提高组 简要题解 小凯的疑惑(数论) 不讲 时间复杂度 大力模拟 奶酪 并查集模板题 宝藏 最优解一定存在一种构造方法是按照深度一步步生成所有的联通性. 枚举一个根,随后设\ ...

  9. 【题解】NOIP2017逛公园(DP)

    [题解]NOIP2017逛公园(DP) 第一次交挂了27分...我是不是必将惨败了... 考虑这样一种做法,设\(d_i\)表示从该节点到n​节点的最短路径,\(dp(i,k)\)表示从\(i\)节点 ...

随机推荐

  1. Python&R&量化 金融之路

    [ 分类 ]- 金融之路 - 闲云孤鹤(人生在世五十年,大千世界一瞬间,浮生若梦,仿佛间,幻境一场,生者无常,终须尽.) - CSDN博客 https://blog.csdn.net/robertso ...

  2. http1.0 1.1 与2.0

    长连接 HTTP 1.0需要使用keep-alive参数来告知服务器端要建立一个长连接,而HTTP1.1默认支持长连接. HTTP是基于TCP/IP协议的,创建一个TCP连接是需要经过三次握手的,有一 ...

  3. scoketio

    服务器代码let net = require('net'); // 创建服务器 let server = net.createServer(); // 定义一个数组 ,存放每一个连接服务器的客户端用户 ...

  4. C# List用法 List介绍

    一.#List泛型集合 集合是OOP中的一个重要概念,C#中对集合的全面支持更是该语言的精华之一. 为什么要用泛型集合? 在C# 2.0之前,主要可以通过两种方式实现集合: a.使用ArrayList ...

  5. IdentityServer4【QuickStart】之使用ResourceOwnerPassword流程来保护API

    使用ResourceOwnerPassword流程来保护API OAuth2.0中的ResourceOwnerPassword授权流程允许一个客户端发送username和password到token服 ...

  6. Azure系列2.1.3 —— BlobEncryptionPolicy

    (小弟自学Azure,文中有不正确之处,请路过各位大神指正.) 网上azure的资料较少,尤其是API,全是英文的,中文资料更是少之又少.这次由于公司项目需要使用Azure,所以对Azure的一些学习 ...

  7. 查看端口占用cmd命令

    查看端口被占用的进程: 在任务管理器中结束进程:

  8. mysql关联、子查询索引优化

    1.驱动表:加索引不起作用,因为全表扫描.表1 left join 表2 ,此时表1是驱动表 被驱动表:给这个加索引.  关联查询  子查询时 尽量不使用not in 或者not exists 而是用 ...

  9. Golang的Json encode/decode以及[]byte和string的转换

    使用了太长时间的python,对于强类型的Golang适应起来稍微有点费力,不过操作一次之后发现,只有这么严格的类型规定,才能让数据尽量减少在传输和解析过程中的错误.我尝试使用Golang创建了一个公 ...

  10. drf实现图片验证码功能

    一.背景 在之前实现过django的图片验证码,有自己实现过的,也有基于django-simple-captcha的,都是基于form表单验证,若自己实现,可以获取相应的标签name便可以获取判断,若 ...