[POI2008]PER
很有思维的一道题
这个题的题面非常简单,出题人很友好,没有搞什么奇怪的背景,(卡农(P3214)的作者看看人家),所以理解题面就是:
一句话题意:
给定一个长度为 \(n\) 的数列,求这个数列是在其全排列中的排名是多少,输出排名 \(mod\) \(m\) 的结果。
赵小兵同学:这不就是个康托展开嘛,看我A掉这个大水题。
于是,他打出了下面这个程序:
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x7f7f7f7f7f
const int one = 1e7+10;
inline void openfile()
{freopen("t.txt","r",stdin);}
namespace zxb
{
int tree[1000005];
int n;
inline int lowbit(int x)
{
return x&-x;
}
inline void update(int x,int y)
{
while(x<=n){
tree[x]+=y;
x+=lowbit(x);
}
}
inline int query(int x)
{
int sum=0;
while(x)
{
sum+=tree[x];
x-=lowbit(x);
}
return sum;
}
int mod;
int jc[1000005];
int a[1000005];
inline short main()
{
//openfile();
jc[0] = jc[1] = 1;
cin >> n >> mod;
for(int i=1;i<=n;i++)
{
jc[i]=(jc[i-1]*i)%mod;
update(i,1);
}
int ans = 0;
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
ans=(ans+((query(a[i])-1)*jc[n-i]) % mod) % mod;
update(a[i],-1);
}
cout<<ans +1<<endl;
return 0;
}
}
signed main() { return zxb::main();}
然后。。。
赵小兵同学翻车记录
旁边的 \(C\) 君看不下去了,转眼就打了一个暴力算法,并对赵小兵同学发来了鄙视
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x7f7f7f7f7f
const int one = 1e7+10;
inline void openfile()
{freopen("t.txt","r",stdin);}
inline int get()
{
int s = 0,f = 1;
register char ch = getchar();
while(!isdigit(ch))
{
if(ch == '-') f= -1;
ch = getchar();
}
while(isdigit(ch))
{
s = s* 10 + ch - '0';
ch = getchar();
}
return s * f;
}
namespace xin
{
int a[one],b[one];
int mod,n;
inline bool comp()
{
for(register int i=1;i<=n;++i)
if(a[i] != b[i])
return false;
return true;
}
inline short main()
{
// openfile();
n = get(); mod = get();
for(register int i=1;i<=n;++i) a[i] = get(),b[i] = a[i];
sort(a+1,a+1+n);
int cnt = 1;
while(next_permutation(a+1,a+n+1))
{
cnt++;
if(comp() == 1)
{
cout<<cnt % mod<<endl;
return 0;
}
}
return 0;
}
}
signed main() { return xin::main();}
\(C\) 君的暴力记录\(C\) 君的暴力记录
\(C\) 君整整比赵小兵同学多了一倍的分数,这时候,坐在一旁的 \(XIN\) 同学看不下去了,但 \(XIN\) 同学一时间也无法想出正解,但是经过 \(XIN\) 同学为期 \(3\) 天的不懈奋斗,终于 \(A\) 掉了这个题目:
赵小冰和 \(C\) 君都想要知道他的思路, \(XIN\) 同学开始讲到:
首先,要考虑每一个数位的贡献值,其实赵小兵同学的第一想法是不错的,但是只能说是不对,因为这个题目存在重复,也存在模数为合数的时候,所以康托展开就不管用了,所以要考虑别的想法,发现全排列就和本身的字典序有关,之后得出计算式:
\]
$cnt $ 就是从 \(i\) 到 $n $ 中 \(j\) 所出现的个数
但是问题就又来了,合数应该怎么处理呢???
最先考虑费马小定理:
\]
可是,模数为合数啊,所以考虑扩展欧几里的求出逆元:
inline void exgcd(int a,int b,int &x,int &y)
{
if(!b) { x = 1; y = 0; return;}
exgcd(b,a%b,y,x);
y -= a / b * x;
}
inline int get_inv(int x,int p)
{
int a,b;
exgcd(x,p,a,b);
return (a % p + p) % p;
}
之后可以用树状数组在 \(log\) 的时间复杂度的情况下求出区间最小值:
namespace xin_bit
{
int s[maxn];
inline int lowbit(int x)
{return x & -x;}
inline void add(int x,int val)
{
while(x <= maxn)
{
s[x] += val;
x += lowbit(x);
}
}
inline int query(int x)
{
register int ret = 0;
while(x)
{
ret += s[x];
x -= lowbit(x);
}
return ret;
}
}
之后来一点小小的转移,将因子分解,之后再合并,最后就可以按照计算式求出本题的答案了。
慷慨的 \(XIN\) 还放出了代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 1e6+10;
namespace xin_io
{
inline int get()
{
int s =0 ,f = 1;
register char ch = getchar();
while(!isdigit(ch))
{
if(ch == '-') f= -1;
ch = getchar();
}
while(isdigit(ch))
{
s = s *10 + ch - '0';
ch = getchar();
}
return s * f;
}
inline void write(int x)
{
if(x < 0) putchar('-'),x = -x;
if(x > 9) write(x/10);
putchar(x % 10 + '0');
}
}
using xin_io::get; using xin_io::write;
inline void openfile()
{freopen("t.txt","r",stdin);}
namespace xin_bit
{
int s[maxn];
inline int lowbit(int x)
{return x & -x;}
inline void add(int x,int val)
{
while(x <= maxn)
{
s[x] += val;
x += lowbit(x);
}
}
inline int query(int x)
{
register int ret = 0;
while(x)
{
ret += s[x];
x -= lowbit(x);
}
return ret;
}
}
namespace xin
{
#define m(c) cout<<sizeof(c) / (1 << 20) << "MB"<<endl
#define min(a,b) (a) < (b) ? (a) : (b)
#define max(a,b) (a) > (b) ? (a) : (b)
int mod;
int n,m;
bool number[maxn];
int prime[maxn];
int i,j,count=0;
inline void xin_shai(int N)
{
memset(number,true,sizeof(number));
for(i=2;i<=N;i++)
{
if(number[i])
prime[count++]=i;
for(j=0;j<count and prime[j]*i<=N;j++)
{
number[prime[j]*i]=false;
if(i%prime[j]==0)
break;
}
}
}
inline void exgcd(int a,int b,int &x,int &y)
{
if(!b) { x = 1; y = 0; return;}
exgcd(b,a%b,y,x);
y -= a / b * x;
}
inline int get_inv(int x,int p)
{
int a,b;
exgcd(x,p,a,b);
return (a % p + p) % p;
}
int cnt[110],link[110][maxn];
int rec1[maxn],rec2[maxn];
int temp,a[maxn],fac[maxn],num_fac = 0;
inline void cont(int &x,int val)
{
for(register int i=1;i<=num_fac;++i)
{
register int zhuan = fac[i];
while(!(x % zhuan))
x/=zhuan,cnt[i] += val;
}
}
inline int get_num()
{
int ret = 1;
for(register int i=1;i<=num_fac;++i)
ret = (ret * link[i][min(rec2[i],cnt[i])] ) % m;
return ret;
}
inline int work()
{
int ans = 0,ret = 1;
rec1[a[n]] = 1; xin_bit::add(a[n],1);
for(register int i=n-1;i>=1;--i)
{
int zhuan = n - i;
cont(zhuan,1);
ret *= zhuan; ret %= m;
zhuan = ++rec1[a[i]];
cont(zhuan,-1);
ret = (ret * get_inv(zhuan,m) + m) % m;
xin_bit::add(a[i],1);
zhuan = get_num();
ans += (ret % m * xin_bit::query(a[i] - 1) % m * zhuan % m + m ) % m;
ans %= m;
}
return ++ans;
}
inline short main()
{
openfile();
n = get(); m = get(); temp = m;
for(register int i=1;i<=n;++i) a[i] = get();
for(register int i=2;i<=sqrt(temp);++i)
if(temp % i == 0)
{
fac[++num_fac] = i;
link[num_fac][0] = 1;
for(register int j=1;j<=maxn;++j)
link[num_fac][j] = link[num_fac][j-1] * i % m,rec2[num_fac] ++;
while(temp % i == 0)temp /= i;
}
if(temp > 1)
{
fac[++num_fac] = temp;
link[num_fac][0] = 1;
for(register int j=1;j<=maxn;++j)
link[num_fac][j] = link[num_fac][j-1] * temp % m,rec2[num_fac]++;
}
int ans = work() % m;
write(ans);
putchar('\n');
return 0;
}
}
signed main() {return xin::main();}
[POI2008]PER的更多相关文章
- [BZOJ1112][POI2008]砖块Klo
[BZOJ1112][POI2008]砖块Klo 试题描述 N柱砖,希望有连续K柱的高度是一样的. 你可以选择以下两个动作 1:从某柱砖的顶端拿一块砖出来,丢掉不要了. 2:从仓库中拿出一块砖,放到另 ...
- [bzoj1122][POI2008]账本BBB
1122: [POI2008]账本BBB Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 402 Solved: 202[Submit][Status ...
- BZOJ 1113: [Poi2008]海报PLA
1113: [Poi2008]海报PLA Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1025 Solved: 679[Submit][Statu ...
- BZOJ 1116: [POI2008]CLO
1116: [POI2008]CLO Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 922 Solved: 514[Submit][Status][ ...
- BZOJ 1112: [POI2008]砖块Klo
1112: [POI2008]砖块Klo Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1736 Solved: 606[Submit][Statu ...
- BZOJ 1124: [POI2008]枪战Maf
1124: [POI2008]枪战Maf Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 617 Solved: 236[Submit][Status ...
- BZOJ 1123: [POI2008]BLO
1123: [POI2008]BLO Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1030 Solved: 440[Submit][Status] ...
- BZOJ 1121: [POI2008]激光发射器SZK
1121: [POI2008]激光发射器SZK Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 792 Solved: 653[Submit][Sta ...
- BZOJ1132: [POI2008]Tro
1132: [POI2008]Tro Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 815 Solved: 211[Submit][Status] ...
- BZOJ1116: [POI2008]CLO
1116: [POI2008]CLO Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 565 Solved: 303[Submit][Status] ...
随机推荐
- 【NX二次开发】获取相邻面UF_MODL_ask_adjac_faces
获取箭头指示的面的相邻面 源码: 1 extern DllExport void ufsta(char *param, int *returnCode, int rlen) 2 { 3 UF_init ...
- 【NX二次开发】NX内部函数,libugui.dll文件中的内部函数
本文分为两部分:"带参数的函数"和 "带修饰的函数". 浏览这篇博客前请先阅读: [NX二次开发]NX内部函数,查找内部函数的方法 带参数的函数: bool A ...
- 【linux】驱动-14-异步通知
目录 前言 14. 异步通知 14.1 异步通知的一些概念 14.2 Linux 信号 14.3 信号接收 14.4 使用流程 14.4.1 参考流程图 14.4.2 分析&编程步骤 14.4 ...
- 「10.16晚」序列(....)·购物(性质)·计数题(DP)
A. 序列 考场不认真读题会死..... 读清题就很简单了,分成若干块,然后块内递增,块外递减,同时使最大的块长为$A$ B. 购物 考场思路太局限了,没有发现性质, 考虑将$a_{i}$,排序前缀和 ...
- 《MySQL面试小抄》索引失效场景验证
我是肥哥,一名不专业的面试官! 我是囧囧,一名积极找工作的小菜鸟! 囧囧表示:小白面试最怕的就是面试官问的知识点太笼统,自己无法快速定位到关键问题点!!! 本期主要面试考点 面试官考点之什么情况下会索 ...
- hive学习笔记之三:内部表和外部表
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- Linux系统安装-C7
1.安装部署操作系统 (1)创建虚拟机,加载系统镜像 (2)进入系统引导界面进行配置 补充:centos7系统网卡名称 默认系统的网卡名称为 eth0 eth1 –centos6 默认系统的网卡名称为 ...
- JS 获取JSON数据的属性
var tballdata= [{ 'tjqd': '', 'A1': '', 'A2': '', 'A3': '', 'A4': '' };] if (typeof tballdata[0] == ...
- OpenMVG 系列 (1):入门简介
1 OpenMVG 简介 全称 Open Multiple View Geometry,是法国人 Pierre Moulon 读博期间开源的一个 C++ 库 最早版本 OpenMVG 0.1 是 ...
- Gym 101206L Daylight Saving Time 根据年月日计算星期
题意: [3月的第二个周日02:00:00 , 3月的第二个周日03:00:00) 这个区间都不是PST或PDT,[11月的第一个周日01:00:00 , 11月的第一个周日02:00:00) 这个区 ...