20170613NOIP模拟赛

3道题目,时间3小时

题目非原创,仅限校内交流使用

题目名称

Graph

Incr

Permutation

文件名

graph

incr

permutation

输入文件

graph.in

incr.in

permutation.in

输出文件

graph.out

incr.out

permutation.out

时间限制

1000ms

1000ms

1000ms

内存限制

256mb

256mb

256mb

测试点数目

10

10

10

测试点分值

10

10

10

是否有部分分

题目类型

传统

传统

传统

 

 

 

 

 

 

 

 

 

 

 

评测环境

 

操作系统:Windows XP Professional SP3

CPU: Intel(R) Pentium(R) CPU G2030 @ 3.00GHz (2CPUs)

系统内存:2GB

评测工具:Cena 0.8.

 

Problem 1 Graph (graph.cpp/c/pas)

【题目描述】

给出 N 个点,M 条边的有向图,对于每个点 v,求 A(v) 表示从点 v 出发,能到达的编号最大的点。

【输入格式】

 1 行,2 个整数 N,M 接下来 M 行,每行 2 个整数 Ui,Vi,表示边 ⟨Ui,Vi⟩。点用 1,2,...,N 编号。

【输出格式】

N 个整数 A(1),A(2),...,A(N)。

【样例输入】

4 3

1 2

2 4

4 3

【样例输出】

4 4 3 4

【数据范围】

对于 60% 的数据,1 ≤ N,K ≤ 10^3;

对于 100% 的数据,1 ≤ N,M ≤ 10^5。

思路

dfs/Tarjan/拓扑序列/bfs皆可。

 

Problem 2 Incr(incr.cpp/c/pas)

【题目描述】

数列 A1,A2,...,AN,修改最少的数字,使得数列严格单调递增。

【输入格式】

1 行,1 个整数 N

2 行,N 个整数 A1,A2,...,AN

【输出格式】

1 个整数,表示最少修改的数字

【样例输入】

3

1 3 2

【样例输出】

1

【数据范围】

对于 50% 的数据,N ≤ 10^3

对于 100% 的数据,1 ≤ N ≤ 10^5,1 ≤ Ai ≤ 10^9

思路

对于每个Ai,先减去i,然后求最长严格上升子序列a;

ans=n-a;

代码实现

 1 #include<cstdio>
 2 const int maxn=1e5+10;
 3 int n,a;
 4 int s[maxn],v[maxn];
 5 int main(){
 6     scanf("%d",&n);
 7     for(int i=1;i<=n;i++) scanf("%d",&s[i]),s[i]-=i;
 8     v[++a]=s[1];
 9     for(int i=1;i<=n;i++){
10         if(v[a]<s[i+1]) v[++a]=s[i+1];
11         else
12         for(int j=1;j<=a;j++)
13         if(s[i+1]<v[j]){v[j]=s[i+1];break;}
14     }
15     printf("%d",n-a);
16     return 0;
17 }

 

Problem 3 Permutation (permutation.cpp/c/pas)

【题目描述】

1 到 N 任意排列,然后在排列的每两个数之间根据他们的大小关系插入“>”和“<”。

问在所有排列中,有多少个排列恰好有K个“<”。

例如排列(3, 4, 1, 5, 2)

3 < 4 > 1 < 5 > 2

共有2个“<”

【输入格式】

N,K

【输出格式】

答案

【样例输入】

5 2

【样例输出】

66

【数据范围】

20%:N <= 10

50%:答案在0..2^63-1内

100%:K < N <= 100

思路

DP方程:f[i][j]=f[i-1][j]*(j+1)+f[i-1][j-1]*(i-j);

代码实现

 1 #include<cstdio>
 2 const int maxn=110;
 3 inline int max_(int x,int y){return x>y?x:y;}
 4 int n,k;
 5 int s[2][110][300];
 6 void tot(int i,int j,int v1,int v2){
 7     int b=max_(s[i^1][j][0],s[i^1][j-1][0]);
 8     for(int a=1;a<=b;a++) s[i][j][a]=s[i^1][j][a]*v1+s[i^1][j-1][a]*v2;
 9     for(int a=1;a<=b;a++)
10     if(s[i][j][a]>999){
11         s[i][j][a+1]+=s[i][j][a]/1000;
12         s[i][j][a]%=1000;
13         if(a==b) b++;
14     }
15     s[i][j][0]=b;
16 }
17 void put(int i,int j){
18     printf("%d",s[i][j][s[i][j][0]]);
19     for(int a=s[i][j][0]-1;a>0;a--)
20     printf("%03d",s[i][j][a]);
21 }
22 int main(){
23     freopen("permutation.in","r",stdin);
24     freopen("permutation.out","w",stdout);
25     scanf("%d%d",&n,&k);
26     s[0][0][0]=s[0][0][1]=s[1][0][0]=s[1][0][1]=1;
27     for(int i=1;i<=n;i++)
28     for(int j=1;j<=k;j++)
29     tot(i&1,j,j+1,i-j);
30     put(n&1,k);
31     return 0;
32 }
原文地址:https://www.cnblogs.com/J-william/p/7001430.html