必做题
P1028 [NOIP2001 普及组] 数的计算
找规律递推即可。
完整代码如下:
#include<iostream>
using namespace std;
int arr[1001], sum[1001];
int main()
{
arr[1] = 1;
sum[1] = 1;
int n;
cin >> n;
for(int i=2 ; i<=n ; i++)
{
arr[i] = 1 + sum[i/2];
sum[i] = sum[i-1] + arr[i];
}
cout << arr[n];
return 0;
}
P1192 台阶问题
递推即可。
完整代码如下:
#include<bits/stdc++.h>
using namespace std;
int steps[100005];
int main()
{
// freopen("D:\\test.txt","r",stdin);
int n,k;
cin>>n>>k;
steps[0] = 1;
for(int i=0 ; i<n ; i++){
for(int j=i+1 ; j-i<=k&&j<=n ; j++){
steps[j] += steps[i];
steps[j] %= 100003;
}
}
cout << steps[n];
return 0;
}
P1044 [NOIP2003 普及组] 栈
分析:对于序列数
n
n
n 欲求
f
(
n
)
f(n)
f(n) ,当
k
k
k 是其输出序列的最后一个数时,比
k
k
k 小的数在
k
k
k 进栈时已经全部出栈,比
k
k
k 大的数在
k
k
k 出栈时已经全部出栈,二者互相独立,满足分布乘法计数原理,即
f
(
k
−
1
)
∗
f
(
n
−
k
)
,
(
1
≤
k
≤
n
)
f(k-1)*f(n-k),(1\le k\le n)
f(k−1)∗f(n−k),(1≤k≤n) 于是我们可以写成一个卷积的形式(Catalan数):
f
(
n
)
=
∑
k
=
1
n
f
(
k
−
1
)
∗
f
(
n
−
k
)
f(n)=\sum_{k=1}^{n}f(k-1)*f(n-k)
f(n)=k=1∑nf(k−1)∗f(n−k)
完整代码如下:
#include<bits/stdc++.h>
using namespace std;
int st[20];
int main()
{
// freopen("D:\\test.txt","r",stdin);
int n;
cin>>n;
st[0] = st[1] = 1;
for(int i=2 ; i<=n ; i++)
for(int j=0 ; j<=i ; j++)
st[i] += st[i-1-j]*st[j];
cout << st[n];
return 0;
}
P1003 [NOIP2011 提高组] 铺地毯
从后向前看
(
x
,
y
)
(x,y)
(x,y) 在不在地毯上就行。
完整代码如下:
#include<bits/stdc++.h>
using namespace std;
struct carpet{
int a,b,g,k;
}arr[10004];
int main()
{
// freopen("D:\\test.txt","r",stdin);
int n,x,y;
cin>>n;
for(int i=1; i<=n ;i++) cin>>arr[i].a>>arr[i].b>>arr[i].g>>arr[i].k;
cin>>x>>y;
int i;
for(i=n ; i>=1 ; i--){
if(x>=arr[i].a && x<=arr[i].a+arr[i].g
&& y>=arr[i].b && y<=arr[i].b+arr[i].k){
cout << i;
break;
}
}
if(i==0) cout << -1;
return 0;
}
选做题
P4994 终于结束的起点
暴力枚举即可。
完整代码如下:
#include<bits/stdc++.h>
using namespace std;
int fib[0x9fffff];
int main()
{
// freopen("D:\\test.txt","r",stdin);
int m,ans;
cin>>m;
fib[0]=0, fib[1]=1;
for(int i=2 ; i<0x9fffff ; i++){
fib[i] = (fib[i-1] + fib[i-2]) % m;
if(fib[i-1]==0 && fib[i]==1){
ans = i-1;
break;
}
}
cout << ans;
return 0;
}
P2615 [NOIP2015 提高组] 神奇的幻方
按照题意写一个模拟,凑合凑合过了。
完整代码如下:
#include<bits/stdc++.h>
using namespace std;
int arr[50][50];
struct Pos{
int row,col;
}pos[2500];
int main()
{
// freopen("D:\\test.txt","r",stdin);
int n;
cin>>n;
arr[1][(n+1)/2] = 1;
pos[1].row=1, pos[1].col=(n+1)/2;
for(int i=2 ; i<=n*n ; i++){
if(pos[i-1].row==1 && pos[i-1].col!=n){
pos[i].row=n,
pos[i].col=pos[i-1].col + 1;
arr[pos[i].row][pos[i].col] = i;
}
else if(pos[i-1].row!=1 && pos[i-1].col==n){
pos[i].row=pos[i-1].row - 1,
pos[i].col=1;
arr[pos[i].row][pos[i].col] = i;
}
else if(pos[i-1].row==1 && pos[i-1].col==n){
pos[i].row=2,
pos[i].col=n;
arr[pos[i].row][pos[i].col] = i;
}
else{
if(arr[pos[i-1].row-1][pos[i-1].col+1]==0){
pos[i].row=pos[i-1].row-1,
pos[i].col=pos[i-1].col+1;
arr[pos[i].row][pos[i].col] = i;
}
else{
pos[i].row=pos[i-1].row+1,
pos[i].col=pos[i-1].col;
arr[pos[i].row][pos[i].col] = i;
}
}
}
for(int i=1 ; i<=n ; i++){
for(int j=1 ; j<=n ; j++)
cout << arr[i][j] << " ";
cout << '\n';
}
return 0;
}
P1011 [NOIP1998 提高组] 车站
因为不知道第二站上下车的人数,不妨设为
b
b
b,暴力枚举
b
b
b 直到找到答案。
完整代码如下:
#include<bits/stdc++.h>
using namespace std;
struct ninzu{
int on,off,tot;
}hito[25];
int main()
{
// freopen("D:\\test.txt","r",stdin);
int n,m,x;
cin>>hito[1].on>>n>>m>>x;
hito[1].tot = hito[2].tot = hito[1].on;
hito[1].off = 0;
for(int b=0 ; b<=20 ; b++){
// 不放心可以枚举更大的范围,本题认为b<=20就可以过数据点了
hito[2].on = hito[2].off = b;
for(int i=3 ; i<=n ; i++){
hito[i].on = hito[i-1].on + hito[i-2].on;
hito[i].off = hito[i-1].on;
hito[i].tot = hito[i-1].tot + hito[i].on - hito[i].off;
}
if(hito[n-1].tot == m){
cout << hito[x].tot;
break;
}
}
return 0;
}