快速乘法-快速幂
Description
从 n 个不同元素中任取 m(m≤n)个元素,按照一定的顺序排列起来,叫做从 n
个不同元素中取出 m 个元素的一个排列。当 m=n 时所有的排列情况叫全排列。
你觉得 xxy 会问你全排列的个数吗?Xxy:这个问题能淹死你,我才不问呢。我
要问的是求 n 的全排列中,先递增后递
减、先递减后递增的全排列的个数。由于答案可能很大,对 p 取余
Input
输入包含多组测试数据每组测试
数据一行两个整数 n,p
Output
对于每组测试数据输出一行表示答案
3 5
4
2 233
0
Hint
设数据组数为 T
对于 10%的数据,n<=10,p<=1000,T=1
对于另外 10%的数据,n<=12,p<=1000,T<=12
对于另外 10%的数据,n<=100,p<=100000,T<=100
对于另外 10%的数据,n<=100000,p<=1000000,T=1
对于另外 10%的数据,n<=100000,p<=1000000,T<=1000
对于另外 20%的数据,n<=1e9,p<=1e9,T<=1000
对于 100%的数据,n<=1e18,p<=1e18,T<=1000
找规律
对于3 我们可以找出所有情况
1 3 2
2 3 1
2 1 3
3 1 2
我们可以发现 4的所有递增递减的情况一定是基于3的所有情况
1 3 2 我们可以将4放在 3前面 1 4 3 2 或者 放在3后面 1 3 4 2
其他情况相同 n全排列的单峰情况 一定可以由n-1的单峰排列情况推出
共2的n次方种
但这不是全部
还有特殊情况 1 2 3 -->1 2 4 3
-->4 1 2 3
3 2 1 -->3 4 2 1
-->3 2 1 4
共 2n+4种
2n用快速幂和快速乘即可
1 #include <cstdio> 2 #include <cctype> 3 #include <algorithm> 4 5 typedef long long LL; 6 7 using namespace std; 8 9 int T; 10 11 LL n,p; 12 13 inline void read(LL&x) { 14 int f=1;register char c=getchar(); 15 for(x=0;!isdigit(c);c=='-'&&(f=-1),c=getchar()); 16 for(;isdigit(c);x=x*10+c-48,c=getchar()); 17 x=x*f; 18 } 19 20 inline LL quick_plus(LL b,LL k) { 21 LL ans=0; 22 while(k) { 23 if(k&1) ans=(ans+b)%p; 24 k>>=1; 25 b=(b+b)%p; 26 } 27 return ans%p; 28 } 29 30 inline LL quick_pow(LL a,LL k) { 31 LL ans=1; 32 while(k) { 33 if(k&1) ans=quick_plus(ans,a); 34 k>>=1; 35 a=quick_plus(a,a); 36 } 37 return ans; 38 } 39 40 int hh() { 41 // freopen("permutation.in","r",stdin); 42 // freopen("permutation.out","w",stdout); 43 while(~scanf("%lld%lld",&n,&p)) { 44 if(n==1||n==2) { 45 printf("0\n"); 46 continue; 47 } 48 LL ans=quick_pow(2,n); 49 LL L=4-p; 50 ans=(ans-L+p)%p; 51 printf("%lld\n",ans); 52 } 53 return 0; 54 } 55 56 int sb=hh(); 57 int main(int argc,char**argv) {;}
作者:乌鸦坐飞机
出处:http://www.cnblogs.com/whistle13326/
新的风暴已经出现
怎么能够停止不前
穿越时空 竭尽全力
我会来到你身边
微笑面对危险
梦想成真不会遥远
鼓起勇气 坚定向前
奇迹一定会出现