首页 写随笔

cdcq(本博客废弃!现用博客:https://www.cnblogs.com/cdcq/)

本博客废弃!现用博客:https://www.cnblogs.com/cdcq/

导航

【HDU5187】contest

真的没有什么会写的东西了QAQ

原题:

As one of the most powerful brushes, zhx is required to give his juniors n problems.
zhx thinks the ith problem's difficulty is i. He wants to arrange these problems in a beautiful way.
zhx defines a sequence {ai} beautiful if there is an i that matches two rules below:
1: a1..ai are monotone decreasing or monotone increasing.
2: ai..an are monotone decreasing or monotone increasing.
He wants you to tell him that how many permutations of problems are there if the sequence of the problems' difficulty is beautiful.
zhx knows that the answer may be very huge, and you only need to tell him the answer module p.

一句话题意:

求有多少种n排列单峰或单调答案膜p

1<=n,p<=1e18

 

n个数里选最最大放在第i个位置,选i-1个数放前面并递增,剩下的放后面并递减,这样有c(i-1,n)种

(注意不能简单地挑i个数放前面剩下的放后面,一定要先有一个最大/小的数在峰上

所有的i加起来就有Σ_{i=0}^{n-1}c(i,n)=2^(n-1)种

先递减再递增同理,所以方案数*2=2^n种

全部递增和全部递减多算了一遍,减2,最后答案是2^n-2

因为膜数很大所以快速幂的同时快速乘

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 using namespace std;
 7 #define ll long long
 8 int rd(){int z=0,mk=1;  char ch=getchar();
 9     while(ch<'0'||ch>'9'){if(ch=='-')mk=-1;  ch=getchar();}
10     while(ch>='0'&&ch<='9'){z=(z<<3)+(z<<1)+ch-'0';  ch=getchar();}
11     return z*mk;
12 }
13 ll n,m;
14 ll mtp(ll x,ll y){
15     ll bs=x,z=0;
16     while(y){  if(y&1)  z=(z+bs)%m;  bs=(bs+bs)%m;  y>>=1;}
17     return z;
18 }
19 ll qcp(ll x,ll y){
20     ll bs=x,z=1;
21     while(y){  if(y&1)  z=mtp(bs,z);  bs=mtp(bs,bs);  y>>=1;}
22     return z;
23 }
24 int main(){freopen("ddd.in","r",stdin);
25     while(scanf("%I64d%I64d",&n,&m)!=EOF){
26         if(n==1){  printf("%I64d\n",n%m);  continue;}
27         printf("%I64d\n",(qcp(2,n)-2+m)%m);
28     }
29     return 0;
30 }
View Code

 

posted on 2017-05-26 13:12  cdcq_old  阅读(272)  评论(0编辑  收藏  举报