NOIP2015|NOIP2015 提高组合集
NOIP 2015 提高组 合集
D1 T1 神奇的幻方
题目让你干啥你就干啥,让你咋走你就咋走就完事儿了
#include
#include
#include
#include
#define N 50
using namespace std;
struct Node
{
int x,y;
}a[N*N];
int ans[N][N];
int main()
{
int n;
cin >> n ;
a[1].x=1;
a[1].y=n/2+1;
ans[1][n/2+1]=1;
for(int i=2;
i<=n*n;
i++)
{
if(a[i-1].x==1&&a[i-1].y!=n)
{
ans[n][a[i-1].y+1]=i;
a[i].x=n;
a[i].y=a[i-1].y+1;
}
else if(a[i-1].x!=1&&a[i-1].y==n)
{
ans[a[i-1].x-1][1]=i;
a[i].x=a[i-1].x-1;
a[i].y=1;
}
else if(a[i-1].x==1&&a[i-1].y==n)
{
ans[a[i-1].x+1][a[i-1].y]=i;
a[i].x=a[i-1].x+1;
a[i].y=a[i-1].y;
}
else
{
if(!ans[a[i-1].x-1][a[i-1].y+1])
{
ans[a[i-1].x-1][a[i-1].y+1]=i;
a[i].x=a[i-1].x-1;
a[i].y=a[i-1].y+1;
}
else
{
ans[a[i-1].x+1][a[i-1].y]=i;
a[i].x=a[i-1].x+1;
a[i].y=a[i-1].y;
}
}
}
for(int i=1;
i<=n;
i++)
{
for(int j=1;
j<=n;
j++) printf("%d ",ans[i][j]);
puts("");
}
}
D1 T2 信息传递
由题目的描述,我们发现这是一个基环内向森林。题目中问的是最多进行多少局,等价于求基环内向森林中所有基环的最小值。模拟即可。
#include
#include
#include
#include
#define N 200001
using namespace std;
int a[N],f[N],v[N];
inline char nc() {static char *p1,*p2,buf[100000];
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
int rd() {int x=0;
char c=nc();
while(!isdigit(c)) c=nc();
while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=nc();
return x;
}
int main()
{
int n=rd(),p,t,ans=0x7f7f7f7f;
for(int i=1;
i<=n;
i++) a[i]=rd();
for(int i=1;
i<=n;
i++)
{
v[i]=1,t=i,p=a[i];
while(f[p]!=i)
{
if(f[p]!=0&&f[p]v[t]+1-v[p]) ans=v[t]+1-v[p];
}
printf("%d",ans);
return 0;
}
D1 T3 斗地主
挖坑代填
D2 T1 跳石头
二分答案,二分出最大可能值,然后暴力验证
#include
#include
#include
#include
using namespace std;
int L,n,m,a[50010];
inline char nc() {static char *p1,*p2,buf[100000];
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
int rd() {int x=0;
char c=nc();
while(!isdigit(c)) c=nc();
while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=nc();
return x;
}
int check(int dist)
{
int last=0,cnt=0;
for(int i=1;
i<=n;
i++)
{
if(a[i]-last>1;
if(check(mid))l=mid;
else r=mid;
}
printf("%d\n",l);
}
D2 T2 子串
动态规划
f[i][j][k]表示当前:A串枚举到了i,B串枚举到了j,已经找到了k个串切使用了a[i]的方案数。
g[i][j][k]................................不管使不使用a[i]的方案数。
然后因为空间问题,f[i][j][k],i压滚动。
转移sb
#include
#include
#include
#include
#define mod 1000000007
#define N 210
using namespace std;
int f[2][N][N],g[2][N][N];
char s1[10010],s2[10010];
int main()
{
int n,m,k;
cin >> n >> m >> k ;
scanf("%s%s",s1+1,s2+1);
int pre=1;
g[1][0][0]=1;
for(int i=1;
i<=n;
i++)
{
// puts("Fuck");
pre^=1;
g[pre][0][0]=1;
for(int j=1;
j<=m;
j++)
{
for(int l=1;
l<=k;
l++)
{
if(s1[i]==s2[j]) (f[pre][j][l]=g[pre^1][j-1][l-1]+f[pre^1][j-1][l])%=mod;
else f[pre][j][l]=0;
(g[pre][j][l]=f[pre][j][l]+g[pre^1][j][l])%=mod;
// if(f[pre][j][l]) printf("%d %d %d\n",i,j,l);
}
}
}
printf("%d\n",g[pre][m][k]);
return 0;
}
D2 T3 运输计划
一眼二分答案,关键是怎么验证。首先,我们对于每次询问,都记录出:这个询问在不建立虫洞的情况下的长度。
紧接着根据我们二分出的mid,对于一次距离大于mid的询问树上查分,记录每条边被多少询问累计过。
然后我们边权下放到点权,对于每条被所有大于mid的询问经过的边,我们判断:是不是长度最长的询问减去这条边对应的边权在mid内即可。
#include
#include
#include
#include
#define N 300010
#define M 300010
using namespace std;
int n,m;
inline char nc() {static char *p1,*p2,buf[100000];
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
int rd() {int x=0;
char c=nc();
while(!isdigit(c)) c=nc();
while(isdigit(c)) x=(x<<3)+(x<<1)+c-'0',c=nc();
return x;
}
struct Line {int x,y,v,lca;
}L[M];
inline bool cmp(const Line &x,const Line &y) {return x.v=dep[y]) x=f[x][i];
}
if(x==y) return x;
for(int i=25;
~i;
i--)
{
if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
}
return f[x][0];
}
void dfs_check(int pos,int fa)
{
for(int i=head[pos];
i;
i=nxt[i]) if(to[i]!=fa)
{
dfs_check(to[i],pos);
o[pos]+=o[to[i]];
}
}
bool check(int x)
{
memset(o,0,sizeof o);
int begin;
for(int i=1;
i<=m;
i++) if(L[i].v>x) {begin=i;
break;
}
// printf("%d\n",begin);
for(int i=begin;
i<=m;
i++)
{
o[L[i].x]++;
o[L[i].y]++;
o[L[i].lca]-=2;
}
dfs_check(1,1);
for(int i=2;
i<=n;
i++)
{
if(o[i]>=m-begin+1&&L[m].v-top[i]<=x)
{
// printf("%d %d %d %d\n",i,L[m].v,top[i],x);
return true;
}
}
return false;
}
void test()
{
puts("Fuck");
for(int i=1;
i<=n;
i++) printf("%d ",top[i]);
puts("");
}
void test1()
{
puts("Shit");
for(int i=1;
i<=m;
i++) printf("%d ",L[i].v);
puts("");
}
int main()
{
n=rd(),m=rd();
int x,y,z;
for(int i=1;
i>1;
if(check(mid)) r=mid-1;
else l=mid+1;
}
// if(m==1&&L[1])
for(int i=r-1;
i<=L[m].v;
i++)
{
if(!check(i)) continue;
printf("%d\n",i);
return 0;
}
puts("0");
}
/*
6 3
1 2 3
1 6 4
3 1 7
4 3 6
3 5 5
3 6
2 5
4 5
*/
【NOIP2015|NOIP2015 提高组合集】转载于:https://www.cnblogs.com/ShuraK/p/9601909.html
推荐阅读
- 托福听力高分备考方案
- 数组常用方法一
- 试论化院的学生自组织
- D034+3组苏曼+《写作这回事》读书笔记
- C语言学习|第十一届蓝桥杯省赛 大学B组 C/C++ 第一场
- python青少年编程比赛_第十一届蓝桥杯大赛青少年创意编程组比赛细则
- Java|Java基础——数组
- 学员+3组杨子涓+202002RIA训练营W3D2+苏格拉底提问法
- 幸福2.0六组90天践行总纲指导方针
- 组织绩效V.S个人绩效