Codeforces Round #663 (Div. 2)
A - Suborrays
题意
构造一个数组,使他的所有\(i---j\)的异或和都大于\(j-i+1\)
分析
因为异或是不进位加法,所以说保证\([i,j]\)中有位数比长度大的数即可
因此,小的数往两边放,大的数往中间放。
C - Cyclic Permutations
题意
根据一个数组生成一个树,对于数组中的任意一个\(a_i\),找到两边最靠近他的且大于他的\(a_j\),则\(i、j\)相连。问对于n大小的数组有多少种排列方式。
分析
但是直接考虑存在环的情况比较复杂,考虑不存在环的情况
不存在环,就是对于每个i ii不能同时向左右连边
也就是有么只有左边有数比它大,要么只有右边有数比它大
换言之就是要么左边都比自己小,要么右边都比自己小
这其实构成了一个单峰函数这其实构成了一个单峰函数这其实构成了一个单峰函数
前面一直递增到峰值n,后面一直递减。
注意到这样一个事实,除了n这个特殊的数
其他数都有比自己大的数,也就是一定会至少往外连一条边其他数都有比自己大的数,也就是一定会至少往外连一条边其他数都有比自己大的数,也就是一定会至少往外连一条边
这样就就必定会连n−1条边,构成一颗树这样就就必定会连n-1条边,构成一颗树这样就就必定会连n−1条边,构成一颗树
在树的基础上,无论多加任何一条边都会形成环在树的基础上,无论多加任何一条边都会形成环在树的基础上,无论多加任何一条边都会形成环
那么想构成树,每个数比自己大的数都落在自己的一侧(保证只向一侧连边)那么想构成树,每个数比自己大的数都落在自己的一侧(保证只向一侧连边)那么想构成树,每个数比自己大的数都落在自己的一侧(保证只向一侧连边)
再次得到结论,前面递增到n,后面递减再次得到结论,前面递增到n,后面递减再次得到结论,前面递增到n,后面递减。
答案就是\(n!-2^{n-1}\)
代码
const int p=1e9+7;
int jie(int n)
{
int ans=1;
for(int i=1;i<=n;i++)
{
ans*=i;
ans%=p;
}
return ans;
}
int qpow(int x,int y)
{
if(y==0)return 1;
if(y%2==0)
{
int temp=qpow(x,y/2);
return temp*temp%p;
}
else
{
return x*qpow(x,y-1)%p;
}
}
main(void)
{
int n=read();
printf("%lld",(jie(n)-qpow(2,n-1)+p)%p);
}