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 }
矩阵行走
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 T3 Code
【样例解释】一种方案为: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 }
来源:博客园
作者:Dark_ring
链接:https://www.cnblogs.com/Darkring/p/11431972.html