[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二次开发】修改dlx对话框标题的方法
修改dlx名称, 修改对话框标题的方法: theDialog->TopBlock()->FindBlock("Dialog")->GetProperties()- ...
- Vue——v-for动态绑定id的问题
问题:在Vue中,会遇到许多个多选框,倘若数量很庞大那么一个一个input框.label节点寻找,这样操作很繁琐. 直接上解决方案吧: html页面: <ul v-for="(item ...
- 【redis前传】自己手写一个LRU策略 | redis淘汰策略
title: 自己手写一个LRU策略 date: 2021-06-18 12:00:30 tags: - [redis] - [lru] categories: - [redis] permalink ...
- CCF CSP认证考试在线评测系统
关于 CCF CSP 认证考试在线评测系统 CCF CSP 认证考试简介 CCF 是中国计算机学会的简称.CCF 计算机软件能力认证(简称 CCF CSP 认证考试)是 CCF 于 2014 年推出, ...
- Linux中系统时间同步ntpdate简介
Linux服务器运行久时,系统时间就会存在一定的误差,一般情况下可以使用date命令进行时间设置,但在做数据库集群分片等操作时对多台机器的时间差是有要求的,此时就需要使用ntpdate进行时间同步.所 ...
- 一文带你了解.Net信号量
本文主要讲解.Net基于Semaphore带大家了解信号量 信号量举例 大家去银行去银行取钱,互斥锁管理的时一个柜台是否正在处理业务,而信号量管理的是整个柜台是否正在处理业务,每当有一个柜台处理完成之 ...
- 37、mysql数据库(dcl)
在数据库中参考:"12.创建mysql用户及赋予用户权限"文件.
- as3.0 Flex 图像处理
as3.0 Flex 图像处理 已知的一些图像处理,主要是得到颜色过滤矩阵,不完整,大家一起来补充. //颜色转换数组,所有的0都是可调值public var colorArray:Array = [ ...
- Java中的自增自减
情况①: for (int i = 0; i < 100; i++) { j = 1 + j++; } System.out.println(j); 结果是 0 !! 这是由于在进行后自增/自减 ...
- nginx 基本配置
server { listen 80; server_name 域名; #access_log /var/log/nginx/admin.log; index index.html index.htm ...