B
Description
美旸旸今天碰到一道简单题。
给你一个数n,代表有1到n这n个数。要你把它们排成一个漂亮的排列。
漂亮的排列是满足下面条件之一的排列:
1. a1...ai递增,ai...an递减
2. a1...ai递减,ai...an递增
漂亮的排列的个数可能非常大,要求你输出个数%p
美旸旸看完题目后不屑一笑,随手敲完代码就AC了。
Input
有多组输入,少于1000组。
每组测试数据有两个数:n,p。(1<= n,p <=1e18)
Output
对于每组测试数据,输出一行答案,个数%p。
Sample Input
2 233
3 5
Sample Output
2
1
HINT
找规律啦,ai要么最大要么最小,把ai位置定好就可以讨论啦
当ai为最大 c(1,n-1)+c(2,n-1)+......+c(n-1,n-1)=2^(n-1)
同理可得ai为最小 2^(n-1)
然后i=1和i=n被重复计算啦
所以得-2
个数为2^n-2
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll mod;
ll mul(ll a,ll b) // a*b 快乘
{
ll ans=0;
while(b)
{
if(b&1)
ans=(ans+a)%mod;
a=(a+a)%mod;
b>>=1;
}
return ans;
}
ll pow(ll a,ll b) // a^b 快速幂
{
ll ans=1;
while(b)
{
if(b&1)
ans=mul(ans,a);
a=mul(a,a);
b>>=1;
}
return ans;
}
int main()
{
ll n;
while(~scanf("%lld %lld",&n,&mod))
{
if(n ==1)
printf("%lld\n",n%mod); // 特判直接输出1就完事
else
printf("%lld\n",((pow(ll(2),n)-2+mod))%mod);
}
return 0;
}
D
Description
Averyboy最近迷上了中国环游戏,但是他绞尽脑汁也不会把环拆下来,于是他请教聪明的你帮他解决问题。
首先,杆子上有n个环,第一个环可以挂上或拆下。如果你想挂上或拆下第n个环,那必须满足以下条件:
1. 第n-1个环是挂上的
2. 前n-2个环是拆下的
问题是把n个环全部拆下需要的最少操作次数。
Input
输入文件每行一个数n,n <= 1e9,最后一行是数字0。
Output
每行输出一个数X,代表最少操作次数。X可能很大,输出X%201807
Sample Input
1
4
0
Sample Output
1
10
HINT
我们继续找规律啦
类似汉诺塔。将环分为三个部分
假设F(n)为对n个环拆下(挂上)所需的操作次数
依题意得F(n)=F(n-2)【拆下】+1+F(n-2)【挂上】+F(n-1)【拆下】
然后造矩阵了
[F(n),F(n-1),1]=A*B^(n-2)
矩阵A为Mat tmp
矩阵B为Mat b
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=3;
LL mod=201807;
struct Mat
{
LL mat[N][N];
};
Mat mul(Mat a,Mat b)//矩阵相乘模板
{
Mat ans;
for(int i=0; i<N; i++)
{
for(int j=0; j<N; j++)
{
ans.mat[i][j]=0;
for(int k=0; k<N; k++)
{
ans.mat[i][j]+=a.mat[i][k]*b.mat[k][j];
ans.mat[i][j]%=mod;
}
}
}
return ans;
}
Mat quickPow(Mat a,int n)//快速幂取模
{
Mat ans= //单位矩阵
{
1,0,0,
0,1,0,
0,0,1
};
while(n)
{
if(n&1)
ans=mul(ans,a);
n>>=1;
a=mul(a,a);
}
return ans;
}
int main()
{
int n;
Mat ans;
while(scanf("%d",&n)&&n)
{
Mat b=
{
1,1,0,
2,0,0,
1,0,1
};
Mat tmp=
{
2,1,1,
0,0,0,
0,0,0
};
if(n == 1) printf("1\n");
else if(n == 2) printf("2\n");
else {
ans=quickPow(b,n-2);
ans=mul(tmp,ans);
cout<<ans.mat[0][0]<<endl;
}
}
return 0;
}