1. 程式人生 > >NOIP2018 普及組全國熱身賽 第四場

NOIP2018 普及組全國熱身賽 第四場

先來看一下我這個蒟蒻的成績吧……
在這裡插入圖片描述
第四名這個就是我啦
其實我那個名字的意義呢——如下圖所示
在這裡插入圖片描述
算了我我我不瞎扯了
以下內容為正文
————————————————分割線—————————————————

A. Hello, A * B

WZB剛學習了輸入輸出,他遇到了一道這樣的題目。

輸入2個整數a和b
保證輸入的a和b在long long範圍之內,即滿足
−9223372036854775808≤a,b≤9223372036854775807
計算a∗b的值,即這兩個數字的乘積。

如果a∗b在 long long 範圍之內,即滿足−9223372036854775808≤a∗b≤9223372036854775807
那麼輸出一行一個整數表示a∗b的結果。

如果a∗b不在long long範圍之內,即越界了,那麼輸出"\b",不包含引號。

輸入描述
輸入只有一行,包含用空格分開的兩個整數,表示a和b。
輸出描述
如果a * b在long long範圍之內,輸出一行一個整數,表示a * b的結果;否則輸出"\b",不包含引號。
樣例輸入1
4294967296 2147483648
樣例輸出1
\b
樣例輸入2
4294967296 -2147483648
樣例輸出2
-9223372036854775808
資料規模與約定
正確計算a∗b可以得到50分
正確輸出"\b"也可以得到50分

這道題的思路很簡單,T1大水題嘛,先計算他們乘積,再用乘積除以一個數,看它等不等於另一個數,如果等於直接輸出,否則……你懂的

#include<bits/stdc++.h>
#pragma GCC optimize(2)
using namespace std;
int main()
{
	long long a,b,c;
	scanf("%lld %lld",&a,&b);
	c=a*b;
	if(c/a==b) printf("%lld",c);
	else printf("\\b");
	return 0;
}

B. 去年今日

輸入一個日期(年月日)

輸出這個日期365天之前的日期(年月日)是什麼

輸入描述
輸入一個日期,共8個數字,以yyyymmdd的格式輸入。

前4位數字表示年份,第5位和第6位表示月份,第7位和第8位表示日期。

輸出描述
輸出一個日期,共8個數字,以yyyymmdd的格式輸出。

前4位數字表示年份,第5位和第6位表示月份,第7位和第8位表示日期。

樣例輸入
20181101
樣例輸出
20171101
資料規模與約定
保證輸入日期合法,年份的範圍是1901到2400(兩端都包括)

對於50%的資料,月日部分一定是11月11日。

這道題想特判過去是基本不可能的,最多50~70,為什麼不行?因為你不可能考慮得那麼全面,所以呢……萬事暴力為先

#include<bits/stdc++.h>
#pragma GCC optimize(2)
using namespace std;
int yue[15]={0,31,250,31,30,31,30,31,31,30,31,30,31,0};
bool judge(int o)
{
    if(o%4==0)
    {
        if((o%100==0&&o%400!=0)||o%3200==0) return false;
        else return true;
    }
    else return false;
    return 0;
}
int main()
{
	int a,b,c;
	scanf("%4d %2d %2d",&a,&b,&c);
	for(int i=1;i<=365;i++)
	{
		c--;
		if(!c)
		{
			b--;
			if(yue[b]!=250) c=yue[b];
			else
			{
				if(judge(a)) c=29;
				else c=28;
			}
		}
		if(!b)
		{
			a--;
			b=12;
			c=yue[12];
		}
	}
	int ans;
	ans=a*10000+b*100+c;
	printf("%d",ans);
	return 0;
}

C. 最長公共子序列

輸入兩個數字序列,求最長公共子序列的長度。

輸入描述
第一行一個n
接下來一行n個數字,表示第一個數字序列ai。
接下來一行n個數字,表示第二個數字序列bi。

輸出描述
輸出一行一個數字,表示最長公共子序列的長度

樣例輸入
6
1 2 3 3 2 1
1 2 3 1 2 3
樣例輸出
4
資料規模與約定
對於100%的資料,n≤3e5,1≤ai, bi≤n,每個數字在序列ai中最多出現三次。
對於30%的資料,n≤3e3
對於另30%的資料,每個數字在序列ai中最多出現一次。

加了個滾動陣列優化還是暴零了,但是……樣例黨萬歲

#include<bits/stdc++.h>
#pragma GCC optimize(2)
using namespace std;
int dp[2][300005];
char a[300005],b[300005];
int main()
{
    int i,j,n;
    bool now,pre;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    	scanf("%d",&a[i]);
    for(int i=0;i<n;i++)
    	scanf("%d",&b[i]);
    for(now=1,pre=0,i=0;i<n;i++)
        for(swap(now,pre),j=0;j<n;j++)
            if(a[i]==b[j]) dp[now][j+1]=dp[pre][j]+1;
            else 
             dp[now][j+1]=dp[pre][j+1]>dp[now][j]?dp[pre][j+1]:dp[now][j];
    printf("%d\n",dp[now][n]);
    return 0;
}

D. 掃雷

相信大家都玩過windows下的小遊戲掃雷。

考慮在一個n x m的棋盤上玩掃雷,行列都從1開始下標,已知所有c個雷的位置,第i個的位置是xi,yi。

對於每個k(0≤k<9)輸出有多少個格子,在8個方向上共有k個雷。

輸入描述
輸入第一行三個整數n, m, c。

接下來c行,每行兩個整數x, y表示雷的位置。

輸出描述
輸出共9個數字,其中第k(0≤k≤9)k(0≤k≤9)個數字表示,有多少個格子,在8個方向上共有k個雷。

樣例輸入
3 3 4
1 1
3 3
1 3
3 1
樣例輸出
0
0
4
0
1
0
0
0
0
資料規模與約定
對於100%的資料,n,m≤1e9, c≤1e5, 1≤xi≤n, 1≤yi≤m,輸入的c個雷的位置互不相同。
對於30%的資料,n,m≤1e3
對於另30%的資料,c≤1e3

對於一個普及組的蒟蒻,離散化和map函式再維護一下就OK了 ,有30分就已經可以滿足了,思路很簡單:1.找到點 2.計算和 3.桶排 4.輸出

#include<bits/stdc++.h>
#pragma GCC optimize(2)
using namespace std;
char mmap[10001][10001];
int box[10];
int dx[10]={0,0,0,1,-1,1,-1,1,-1};
int dy[10]={0,1,-1,0,0,1,-1,-1,1};
int dfs(int x,int y)
{
	int s=0;
	for(int i=1;i<=8;i++)
	{
		int sx=x+dx[i];
		int sy=y+dy[i];
		if(mmap[sx][sy]=='o') s++;
	}
	return s;
}
int main()
{
	int n,m,c;
	int x,y;
	scanf("%d %d %d",&n,&m,&c);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			mmap[i][j]='x';
	for(int i=1;i<=c;i++)
	{
		scanf("%d %d",&x,&y);
		mmap[x][y]='o';
	}
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			if(mmap[i][j]!='o') box[dfs(i,j)]++;
	for(int i=0;i<9;i++)
		printf("%d\n",box[i]);
	return 0;
}