洛谷八连测第一轮

Posted 友人A

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷八连测第一轮相关的知识,希望对你有一定的参考价值。

T1

SOL君(炉石主播)和SOL菌(完美信息教室讲师)是好朋友。

题目描述

SOL君很喜欢阶乘。而SOL菌很喜欢研究进制。

这一天,SOL君跟SOL菌炫技,随口算出了n的阶乘。

SOL菌表示不服,立刻就要算这个数在k进制表示下末尾0的个数。

但是SOL菌太菜了于是请你帮忙。

输入输出格式

输入格式:

 

每组输入仅包含一行:两个整数n,k。

 

输出格式:

 

输出一个整数:n!在k进制下后缀0的个数。

 

输入输出样例

输入样例#1:
10 40
输出样例#1:
2

说明

对于20%的数据,n <= 1000000, k = 10

对于另外20%的数据,n <= 20, k <= 36

对于100%的数据,n <= 10^12,k <= 10^12

————————————————————————————

这道题其实就是判断一下n!是否是n^k的倍数 k取个max就是答案了

但是因为n这么大 你不可能直接算 这个时候就要分解质因数取个min辣

技术分享
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define LL long long
using std::min;
LL n,k,ans;
LL q[1007],cnt,h[1007];
void prepare(){
    for(LL x=2;x*x<=k;x++)if(k%x==0){
        q[++cnt]=x;
        while(k%x==0) h[cnt]++,k/=x;
    }
    if(k!=1) q[++cnt]=k,h[cnt]=1;
}
int main(){
    while(scanf("%lld %lld",&n,&k)==2){
        memset(h,0,sizeof(h));
        ans=0x7fffffffffffffff; 
        cnt=0; prepare();
        for(int i=1;i<=cnt;i++){
            LL ly=0;
            for (long long x=q[i];x<=n;x*=q[i]) ly+=n/x;
            ans=min(ans,ly/h[i]);
        }printf("%lld\n",ans);
    }
    return 0;
}
View Code

T2

 

题目背景

 

小强和阿米巴是好朋友。

 

题目描述

 

小强喜欢数列。有一天,他心血来潮,写下了三个长度均为n的数列。

 

阿米巴也很喜欢数列。但是他只喜欢其中一种,波动数列。

 

阿米巴把他的喜好告诉了小强。小强便打算找出这三个数列内的最长波动数列。

 

也就是说,如果我们将三个数列记做a[n][3],他必须要构造一个二元组序列:<p[i], q[i]>,使得对于任何 i>1 有:

 

p[i] > p[i-1]

 

若q[i] = 0,a[p[i]][q[i]] >= a[p[i-1]][q[i-1]]

 

若q[i] = 1,a[p[i]][q[i]] <= a[p[i-1]][q[i-1]]

 

若q[i] = 2,只要保持段内同向即可(就是对于连续的一段q[i]=2,要么都有a[p[i]][q[i]] >= a[p[i-1]][q[i-1]],要么都有a[p[i]][q[i]] <= a[p[i-1]][q[i-1]])。

 

小强希望这个二元组序列尽可能长。

 

提示:当q[i] != q[i-1]时,数列的增减性由q[i]而非q[i-1]决定。

 

清晰版题目描述

 

小强拿到一个3×n的数组,要在每一列选一个数(或者不选),满足以下条件:

 

1.如果在第一行选,那它必须大于等于上一个数

 

2.如果在第二行选,那么必须小于等于上一个数

 

3.如果在第三行选,对于连续的一段在第三行选的数,必须满足方向相同(都小于等于上一个数或者都大于等于上一个数)

 

输入输出格式

输入格式:

 

 

输入包含4行。

 

第一行一个数n,表示数列长度。

 

第2、3、4行,每行n个整数,分别表示三个数列。

 

 

输出格式:

 

 

输出仅包含一个整数,即最长波动数列的长度。

 

 

 

输入输出样例

 

输入样例#1:
6
1 2 3 6 5 4
5 4 3 7 8 9
1 2 3 6 5 4
输出样例#1:
6

 

说明

 

对于20%的数据,n <= 10, m <= 1000

 

对于60%的数据,n <= 1000, m <= 1000

 

对于100%的数据, n <= 100000, m <= 1000000000

 

其中m = max|a[i]|

 

样例解释:

 

取第三行1 2 3(增),然后取第1行6(增),然后取第三行5 4(减),长度为6。

这道题f[i][0/1/2/3]分别表示在第i列第j行(0增1减2(2)增3(3)减)

暴力是枚举前面所有行 复杂度n^2 树状数组维护一下前(后)缀和就可以辣

技术分享
#include<cstdio>
#include<cstring>
#include<algorithm>
using std::max;
using std::sort;
using std::unique;
using std::lower_bound;
const int M=4e5+7;
int read(){
    int ans=0,f=1,c=getchar();
    while(c<0||c>9){if(c==-) f=-1; c=getchar();}
    while(c>=0&&c<=9){ans=ans*10+(c-0); c=getchar();}
    return ans*f;
}
int ans,f[M][15],n,v[M][15];
int q[3*M],cnt;
#define lowbit(x) x&-x
struct pos{
    int s[3*M];
    pos(){memset(s,0,sizeof(s));}
    //qian
    void ins2(int x,int w){
        while(x<=cnt){
            s[x]=max(s[x],w);
            x+=lowbit(x);
        }
    }
    int push2(int x){
        int ans=0;
        while(x){
            ans=max(ans,s[x]);
            x-=lowbit(x);
        }
        return ans;
    }
    //hou
    void ins1(int x,int w){
        while(x){
            s[x]=max(s[x],w);
            x-=lowbit(x);
        }
    }
    int push1(int x){
        int ans=0;
        while(x<=cnt){
            ans=max(ans,s[x]);
            x+=lowbit(x);
        }
        return ans;
    }
}s0,s1,s2,s3;
int main(){
    n=read();
    for(int j=0;j<=2;j++) for(int i=1;i<=n;i++) v[i][j]=read(),q[++cnt]=v[i][j];
    sort(q+1,q+1+cnt); cnt=unique(q+1,q+1+cnt)-q-1;
    for(int j=0;j<=2;j++) for(int i=1;i<=n;i++) v[i][j]=lower_bound(q+1,q+1+cnt,v[i][j])-q;
    f[1][0]=f[1][1]=f[1][2]=f[1][3]=1;
    s0.ins2(v[1][0],f[1][0]); s0.ins2(v[1][1],f[1][1]);
    s0.ins2(v[1][2],f[1][2]); s0.ins2(v[1][2],f[1][3]);
    s1.ins1(v[1][0],f[1][0]); s1.ins1(v[1][1],f[1][1]);
    s1.ins1(v[1][2],f[1][2]); s1.ins1(v[1][2],f[1][3]);
    s2.ins2(v[1][0],f[1][0]); s2.ins2(v[1][1],f[1][1]); s2.ins2(v[1][2],f[1][2]);
    s3.ins1(v[1][0],f[1][0]); s3.ins1(v[1][1],f[1][1]); s3.ins1(v[1][2],f[1][3]);
    for(int i=2;i<=n;i++){
        f[i][0]=1; f[i][0]=max(f[i][0],s0.push2(v[i][0])+1);
        f[i][1]=1; f[i][1]=max(f[i][1],s1.push1(v[i][1])+1);
        f[i][2]=1; f[i][2]=max(f[i][2],s2.push2(v[i][2])+1);
        f[i][3]=1; f[i][3]=max(f[i][3],s3.push1(v[i][2])+1);
        int sum=max(max(f[i][0],f[i][1]),max(f[i][2],f[i][3]));
        s0.ins2(v[i][0],f[i][0]); s0.ins2(v[i][1],f[i][1]);
        s0.ins2(v[i][2],f[i][2]); s0.ins2(v[i][2],f[i][3]);
        s1.ins1(v[i][0],f[i][0]); s1.ins1(v[i][1],f[i][1]);
        s1.ins1(v[i][2],f[i][2]); s1.ins1(v[i][2],f[i][3]);
        s2.ins2(v[i][0],f[i][0]); s2.ins2(v[i][1],f[i][1]); s2.ins2(v[i][2],f[i][2]);
        s3.ins1(v[i][0],f[i][0]); s3.ins1(v[i][1],f[i][1]); s3.ins1(v[i][2],f[i][3]);
        ans=max(ans,sum);
    }printf("%d\n",ans);
    return 0;
}
View Code

T3

题目背景

毒奶色和F91是好朋友。

题目描述

他们经常在一起玩一个游戏,不,不是星际争霸,是国际象棋。

毒奶色觉得F91是一只鸡。他在一个n×n的棋盘上用黑色的城堡(车)、骑士(马)、主教(象)、皇后(副)、国王(帅)、士兵(卒)摆了一个阵。

然而F91觉得毒奶色是一只鸡。他发起了挑战:他要操纵一个白色骑士,不经过任何一个棋子的攻击范围(F91可以连续行动,而毒奶色的棋子不会动,除非白骑士进入了对方的攻击范围),并击杀毒奶色的国王(即进入黑国王所在的位置)。

请告诉F91他最少需要多少步骤来完成这一项壮举。

注意:

1.当F91的白骑士走到毒奶色的棋子所在的格子上的时候,会击杀(吃掉)该棋子。这个棋子也就不再对F91的白骑士有威胁了。

2.如果白骑士开场就在黑子的攻击范围内,则立刻被击杀、F91立刻失败。

3.即使白骑士在攻击王的瞬间进入了其他棋子攻击范围(即其他棋子“看护”着王所在的格子),依然算F91获胜。

攻击范围:

城堡:横、竖方向所有位置,直到被一个其他棋子阻拦。

..#..
..#..
##C##
..#..
..#..

骑士:横2竖1或者横1竖2的所有位置(最多8个,类似日字)。

.#.#.
#...#
..K..
#...#
.#.#.

主教:斜向(45°)所有位置,直到被一个其他棋子阻拦。

#...#
.#.#.
..B..
.#.#.
#...#

皇后:城堡和主教的结合体(既能横/竖向攻击,也能45°角斜向攻击,直到被其他棋子阻挡)。

#.#.#
.###.
##Q##
.###.
#.#.#

国王:身边8连通位置的8个格子。

.....
.###.
.#X#.
.###.
.....

士兵:左下方/右下方(45°)的格子(最多2个)。

.....
.....
..P..
.#.#.
.....

其中字母表示棋子类型,参考输入格式。

‘#’表示可攻击范围。

输入输出格式

输入格式:

 

输入包含多组数据。

每一组数据中,第一行一个整数n表示棋盘规模。

接下来n行,每行一个长度为n的字符串。描述棋盘的格局。

其中:

.表示空

O表示白骑士

C表示黑城堡

K表示黑骑士

B表示黑主教

Q表示黒皇后

X表示黑国王

P表示黑士兵

 

输出格式:

 

对于每一个测试数据,每行输出一个整数,表示F91的最小步数。

如果无论F91如何行动也无法击杀黑国王,输出-1。

 

输入输出样例

输入样例#1:
8
...X....
........
........
........
........
........
........
......O.
输出样例#1:
4
输入样例#2:
8
......X.
........
.O......
...P.Q.C
.....B..
........
...K....
........
输出样例#2:
7

说明

输入最多包含5组数据。

对于20%的数据,毒奶色只有国王。n <= 8。

对于30%的数据,毒奶色只有国王、骑士。n <= 8。

对于60%的数据,毒奶色只有国王、骑士、王后。n <= 50。

对于100%的数据,毒奶色可以有全套16颗棋子(2城堡,2骑士,2主教,1后,1王,8兵)。n <= 50。

温馨提示:

时间限制可能比想象之中还要更紧一点,请注意实现细节以保证性能。

样例2解释:

一种可行的做法是:

......X.
.3..6...
.O5.....
4.2P.Q.C
1....B..
........
...K....
........

这题有点小复杂QAQ
因为棋子的最多16个而且王可以压掉还有黑骑士(因为骑士不可能吃骑士)所以就剩13个就可以压了
f[i][j][s]表示走到i j 黑棋子的状态为s的步数 然后慢慢转移咯QAQ 预处理+bfs 6k+
技术分享
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
const int inf=0x3f3f3f3f;
int read(){
    int ans=0,f=1,c=getchar();
    while(c<0||c>9){if(c==-) f=-1; c=getchar();}
    while(c>=0&&c<=9){ans=ans*10+(c-0); c=getchar();}
    return ans*f;
}
char c[205][205];
struct node{char c; int x,y;}f[1233];
int n,cnt,sx,sy,ex,ey;
int map[205][205];
bool vis[(1<<13)+7][205][205],ly[205][205];
int xx[8]={1,1,-1,-1,2,2,-2,-2},yy[8]={2,-2,2,-2,1,-1,1,-1};
bool pd(int x,int y){return (x>=1&&x<=n&&y>=1&&y<=n);}
void prepare(int s){
    int nx,ny;
    for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) vis[s][i][j]=ly[i][j];
    for(int i=0;(1<<i)<=s;i++)if((1<<i)&s){
        if(f[i].c==C){
            nx=f[i].x-1; ny=f[i].y;
            while(pd(nx,ny)&&map[nx][ny]!=-inf&&(map[nx][ny]==-1||!(s&(1<<map[nx][ny])))) vis[s][nx][ny]=1,nx--;
            if(pd(nx,ny)&&map[nx][ny]!=-inf&&(map[nx][ny]!=-1&&(s&(1<<map[nx][ny])))) vis[s][nx][ny]=1;
            nx=f[i].x+1; ny=f[i].y;
            while(pd(nx,ny)&&map[nx][ny]!=-inf&&(map[nx][ny]==-1||!(s&(1<<map[nx][ny])))) vis[s][nx][ny]=1,nx++;
            if(pd(nx,ny)&&map[nx][ny]!=-inf&&(map[nx][ny]!=-1&&(s&(1<<map[nx][ny])))) vis[s][nx][ny]=1;
            nx=f[i].x; ny=f[i].y-1;
            while(pd(nx,ny)&&map[nx][ny]!=-inf&&(map[nx][ny]==-1||!(s&(1<<map[nx][ny])))) vis[s][nx][ny]=1,ny--;
            if(pd(nx,ny)&&map[nx][ny]!=-inf&&(map[nx][ny]!=-1&&(s&(1<<map[nx][ny])))) vis[s][nx][ny]=1;
            nx=f[i].x; ny=f[i].y+1;
            while(pd(nx,ny)&&map[nx][ny]!=-inf&&(map[nx][ny]==-1||!(s&(1<<map[nx][ny])))) vis[s][nx][ny]=1,ny++;
            if(pd(nx,ny)&&map[nx][ny]!=-inf&&(map[nx][ny]!=-1&&(s&(1<<map[nx][ny])))) vis[s][nx][ny]=1;
        }
        else if(f[i].c==B){
            nx=f[i].x-1; ny=f[i].y-1;
            while(map[nx][ny]!=-inf&&pd(nx,ny)&&map[nx][ny]!=-inf&&(map[nx][ny]==-1||!(s&(1<<map[nx][ny])))) vis[s][nx][ny]=1,nx--,ny--;
            if(pd(nx,ny)&&map[nx][ny]!=-inf&&(map[nx][ny]!=-1&&(s&(1<<map[nx][ny])))) vis[s][nx][ny]=1;
            nx=f[i].x+1; ny=f[i].y+1;
            while(pd(nx,ny)&&map[nx][ny]!=-inf&&(map[nx][ny]==-1||!(s&(1<<map[nx][ny])))) vis[s][nx][ny]=1,nx++,ny++;
            if(pd(nx,ny)&&map[nx][ny]!=-inf&&(map[nx][ny]!=-1&&(s&(1<<map[nx][ny])))) vis[s][nx][ny]=1;
            nx=f[i].x-1; ny=f[i].y+1;
            while(pd(nx,ny)&&map[nx][ny]!=-inf&&(map[nx][ny]==-1||!(s&(1<<map[nx][ny])))) vis[s][nx][ny]=1,nx--,ny++;
            if(pd(nx,ny)&&map[nx][ny]!=-inf&&(map[nx][ny]!=-1&&(s&(1<<map[nx][ny])))) vis[s][nx][ny]=1;
            nx=f[i].x+1; ny=f[i].y-1;
            while(pd(nx,ny)&&map[nx][ny]!=-inf&&(map[nx][ny]==-1||!(s&(1<<map[nx][ny])))) vis[s][nx][ny]=1,nx++,ny--;
            if(pd(nx,ny)&&map[nx][ny]!=-inf&&(map[nx][ny]!=-1&&(s&(1<<map[nx][ny])))) vis[s][nx][ny]=1;
        }
        else if(f[i].c==Q){
            nx=f[i].x-1; ny=f[i].y;
            while(pd(nx,ny)&&map[nx][ny]!=-inf&&(map[nx][ny]==-1||!(s&(1<<map[nx][ny])))) vis[s][nx][ny]=1,nx--;
            if(pd(nx,ny)&&map[nx][ny]!=-inf&&(map[nx][ny]!=-1&&(s&(1<<map[nx][ny])))) vis[s][nx][ny]=1;
            nx=f[i].x+1; ny=f[i].y;
            while(pd(nx,ny)&&map[nx][ny]!=-inf&&(map[nx][ny]==-1||!(s&(1<<map[nx][ny])))) vis[s][nx][ny]=1,nx++;
            if(pd(nx,ny)&&map[nx][ny]!=-inf&&(map[nx][ny]!=-1&&(s&(1<<map[nx][ny])))) vis[s][nx][ny]=1;
            nx=f[i].x; ny=f[i].y-1;
            while(pd(nx,ny)&&map[nx][ny]!=-inf&&(map[nx][ny]==-1||!(s&(1<<map[nx][ny])))) vis[s][nx][ny]=1,ny--;
            if(pd(nx,ny)&&map[nx][ny]!=-inf&&(map[nx][ny]!=-1&&(s&(1<<map[nx][ny])))) vis[s][nx][ny]=1;
            nx=f[i].x; ny=f[i].y+1;
            while(pd(nx,ny)&&map[nx][ny]!=-inf&&(map[nx][ny]==-1||!(s&(1<<map[nx][ny])))) vis[s][nx][ny]=1,ny++;
            if(pd(nx,ny)&&map[nx][ny]!=-inf&&(map[nx][ny]!=-1&&(s&(1<<map[nx][ny])))) vis[s][nx][ny]=1;
            nx=f[i].x-1; ny=f[i].y-1;
            while(pd(nx,ny)&&map[nx][ny]!=-inf&&(map[nx][ny]==-1||!(s&(1<<map[nx][ny])))) vis[s][nx][ny]=1,nx--,ny--;
            if(pd(nx,ny)&&map[nx][ny]!=-inf&&(map[nx][ny]!=-1&&(s&(1<<map[nx][ny])))) vis[s][nx][ny]=1;
            nx=f[i].x+1; ny=f[i].y+1;
            while(pd(nx,ny)&&map[nx][ny]!=-inf&&(map[nx][ny]==-1||!(s&(1<<map[nx][ny])))) vis[s][nx][ny]=1,nx++,ny++;
            if(pd(nx,ny)&&map[nx][ny]!=-inf&&(map[nx][ny]!=-1&&(s&(1<<map[nx][ny])))) vis[s][nx][ny]=1;
            nx=f[i].x-1; ny=f[i].y+1;
            while(pd(nx,ny)&&map[nx][ny]!=-inf&&(map[nx][ny]==-1||!(s&(1<<map[nx][ny])))) vis[s][nx][ny]=1,nx--,ny++;
            if(pd(nx,ny)&&map[nx][ny]!=-inf&&(map[nx][ny]!=-1&&(s&(1<<map[nx][ny])))) vis[s][nx][ny]=1;
            nx=f[i].x+1; ny=f[i].y-1;
            while(pd(nx,ny)&&map[nx][ny]!=-inf&&(map[nx][ny]==-1||!(s&(1<<map[nx][ny])))) vis[s][nx][ny]=1,nx++,ny--;
            if(pd(nx,ny)&&map[nx][ny]!=-inf&&(map[nx][ny]!=-1&&(s&(1<<map[nx][ny])))) vis[s][nx][ny]=1;
        }
        else if(f[i].c==P){
            vis[s][f[i].x+1][f[i].y+1]=1;
            vis[s][f[i].x+1][f[i].y-1]=1;
        }
    }
}
struct pos{int x,y,step,s;};
std::queue<pos>q;
bool ca[(1<<13)+7][55][55];
void bfs(){
    while(!q.empty()) q.pop();
    q.push((pos){sx,sy,0,(1<<cnt)-1});
    ca[(1<<cnt)-1][sx][sy]=1;
    if(vis[(1<<cnt)-1][sx][sy]){printf("-1\n"); return ;}
    while(!q.empty()){
        pos p=q.front(); q.pop();
        int s=p.s;
        for(int i=0;i<8;i++){
            int nx=p.x+xx[i],ny=p.y+yy[i];
            if(nx==ex&&ny==ey){printf("%d\n",p.step+1); return ;}
            if(map[nx][ny]==-inf||nx<1||nx>n||ny<1||ny>n||(vis[s][nx][ny])||ca[s][nx][ny]) continue;
            if(map[nx][ny]!=-1&&((1<<map[nx][ny])&s)) q.push((pos){nx,ny,p.step+1,s-((1<<map[nx][ny])&s)}),ca[s-((1<<map[nx][ny])&s)][nx][ny]=1;
            else q.push((pos){nx,ny,p.step+1,s}),ca[s][nx][ny]=1;
        }
    }
    printf("-1\n");
}
int main(){
    //freopen("gg.out","r",stdin);
    while(scanf("%d",&n)==1){
        cnt=0;
        memset(ly,0,sizeof(ly));
        memset(vis,0,sizeof(vis));
        memset(ca,0,sizeof(ca));
        memset(map,0,sizeof(map));
        for(int i=1;i<=n;i++) scanf("%s",c[i]+1);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if(c[i][j]==.) map[i][j]=-1;
                else if(c[i][j]==O) sx=i,sy=j,map[i][j]=-1;
                else if(c[i][j]==X){
                    map[i][j]=-inf;
                    ex=i; ey=j;
                    if(j>1) ly[i][j-1]=1; if(j<n) ly[i][j+1]=1;
                    if(i>1) ly[i-1][j]=1; if(i<n) ly[i+1][j]=1;
                    if(i>1&&j>1) ly[i-1][j-1]=1; if(i&&j<n) ly[i-1][j+1]=1;
                    if(i<n&&j>1) ly[i+1][j-1]=1; if(i<n&&j<n) ly[i+1][j+1]=1;
                }
                else if(c[i][j]==K){
                    map[i][j]=-inf;
                    for(int k=0;k<8;k++) if(pd(i+xx[k],j+yy[k])) ly[i+xx[k]][j+yy[k]]=1;
                }
                else f[cnt]=(node){c[i][j],i,j},map[i][j]=cnt++;
            }
        }
        for(int s=0;s<(1<<cnt);s++) prepare(s); 
        //for(int s=0;s<(1<<cnt);s++,puts("")) for(int i=1;i<=n;i++,puts("")) for(int j=1;j<=n;j++) printf("[%d] ",vis[s][i][j]); puts("");
        bfs();
    }
    return 0;
}
View Code

 

 

 


















以上是关于洛谷八连测第一轮的主要内容,如果未能解决你的问题,请参考以下文章

洛谷八连测R5whzzt-Confidence

洛谷八连测R5whzzt-Warmth

洛谷 八连测 R4

洛谷八连测R5 题解

洛谷八连测R6yanQval-不可逆的重启动

洛谷八连测R6