NOIP提高组 模拟赛 Day1

匿名 (未验证) 提交于 2019-12-02 23:56:01

T1 单峰数计数

Description

一个n的全排列A[i]是单峰的,当且仅当存在某个x使得A[1]<A[2]<...<A[x]>A[x+1]>...> A[n]。例如,对于9的全排列,125798643是一个单峰排列,123456789也是一个单峰排列,但356298741就不是。试求n的单峰全排列的个数。

Input

输入一个数n。

Output

输出n的全排列中单峰排列的个数。由于这个数可能很大,因此你只需要输出它mod 1234567的值。

Sample Input

3
Sample Output
4

Hint

##### 样例解释
共有以下4种方案:
123
132
231
321
##### 数据规模
对于20%的数据,n<=25。
对于100%的数据,n<=2*10^9。
对于100%的数据,显然时间复杂度在O(logn)以下。
所以~手动打表找规律。
当n=1时 只有1种情况:1
当n=2时 有2种情况:12 21
当n=3时 有4种情况:即样例解释
当n=4时 有8种情况:1234 1243 1342 1432 2341 2431 3421 4321
当n=5时 有16种情况:12345 12354 12453 12543 13452 13542 14532 15432 23451 24531 23541 25431 34521 35421 45321 54321
当n=6时 有32种情况,这里不方便举出了。
所以n=k时,有2k-1种情况,快速幂。
实际上,我们可以假设1放中间,后面每个数都可以放在这串数的两边,并且满足单峰。
 1 #include<bits/stdc++.h>  2 #define int long long  3 #define P 1234567  4 using namespace std;  5   6 int n;  7   8 int qpow(int x,int y)  9 { 10     int ans=1,b=x; 11     while(y!=0) 12     { 13         if(y&1) ans=ans*b%P; 14         b=b*b%P; 15         y>>=1; 16     } 17     return ans; 18 } 19 signed main(){ 20     scanf("%lld",&n); 21     if(n==1) 22     { 23         printf("1"); 24         return 0; 25     } 26     printf("%lld",qpow(2,n-1)); 27     return 0; 28 }
T1 Code
矩阵行走
Description
Sample Input
4
1 2 3 4
1 5 3 2
8 1 3 4
3 2 1 5
Sample Output
13
Hint
【数据规模】对于20%的数据,n<=10。对于100%的数据,n <= 100, 每块地上的数字的绝对值不超过300。
典型动态规划。
定义f[i][j][k]表示走到第i步时,一个人站在横坐标为j的格子上,另一个人站在横坐标为i的格子上,当前答案(差值)的最大值。
那么第一个人的位置为(j,i-j+1),第二个人的位置是(k,i-k+1)。
f[i][j][k]=max(f[i-1][j][k-1],f[i-1][j-1][k])+abs(a[j][i-j+1],a[k][i-k+1])
时间复杂度O(n3)
T3 数字转换
Description
Sample Input
7
Sample Output
3
Hint
【样例解释】一种方案为:4→3→1→7。
【数据规模】对于10%的数据,n<10。对于30%的数据,n<100。对于100%的数据,n<=50000。
可以用树形Dp做
首先,要找每个数的约数和。
其次,在一个数和他的约数和之间建一条边,边长为1。
显然,这就是典型的最长链问题了。
在每个点记录当前的第一长链f1和第二长链f2,最后f1+f2就是经过该点的最长链。
 1 #include<bits/stdc++.h>  2 #define MAXN 50009  3 using namespace std;  4   5 int f1[MAXN],f2[MAXN],sum[MAXN],n;  6 int main(){  7     scanf("%d",&n);  8     for(int i=1;i<n;i++)  9         for(int t=(i<<1);t<=n;t+=i) sum[t]+=i; 10     for(int i=n;i>0;i--) 11     { 12         int t=sum[i]; 13         if(t>=i) continue; 14         if(f1[i]+1>f1[t]) f2[t]=f1[t],f1[t]=f1[i]+1; 15         else if(f1[i]+1>f2[t]) f2[t]=f1[i]+1; 16     } 17     int ans=-1; 18     for(int i=1;i<=n;i++) ans=max(ans,f1[i]+f2[i]); 19     printf("%d",ans); 20     return 0; 21 } 
T3 Code
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!