[codechef MEXDIV]Mex division
2024-10-21 23:10:58
题目链接:https://vjudge.net/contest/171650#problem/I
直接用set+dp水过去了。。。
/*
设dp[i]表示前i个做划分满足条件的方案数
有一个显然的转移方程dp[i]=sigma(dp[j]) t<=j<=i-1
其中t是满足mex(a[t..i-1])<=k的最小的t
然后我们现在是想得到,对于每个位置这个t是多少,如果知道了这个,就可以很容易的转移了 首先,考虑,如果k>n,那么不管怎么选,都是会满足条件的啊!(就算把所有的数都选出来,mex也就是k吧)
所以对于k>n,直接输出2^(n-1)
当然k=0的时候特判一下,这样每个i对应的t都是存在的,至少有一个i 现在考虑k<=n的情况,直接用一个multiset记录[1,k]里的数的出现情况
首先,把[0,k]全部都放进multiset,遇到一个新的数,就erase,查询集合里最小的数就是mex 假设现在想得到第i个位置的t,上次求得的i-1对应的t是t'
那么如果a[i]已经在集合中被删去了,那这次对应的肯定还是t'
如果a[i]没有从集合中删去,就把a[i]从集合中删去(当然,如果a[i]>k直接不用管)
考虑到随着i的增大,t肯定是往右走的
如果删去以后集合是空集了,那t'就需要右移了,直到出现一个[0,k]之间的,并且在a[t+1..i]没有出现过的数
是否出现过,只需要记一个右边第一个跟它相等的数就可以了
*/ #include<bits/stdc++.h>
using namespace std; const int maxn=;
int a[maxn];
int t[maxn];
int e[maxn];
long long dp[maxn];
long long predp[maxn];
pair<int,int> p[maxn];
set<int> S; const long long md=;
long long fp(long long a,long long k)
{
long long res=;
a%=md;
while(k)
{
if(k&)res=res*a%md;
a=a*a%md;
k>>=;
}
return res;
} int main()
{
int n,k;
scanf("%d%d",&n,&k);
for (int i=;i<=n;i++) scanf("%d",&a[i]);
if (k>n)
{
printf("%lld",fp(,n-));
return ;
}
if (k==)
{
bool yl=false;
for (int i=;i<=n;i++)
{
if (a[i]==)
{
yl=true;
break;
}
}
if (yl) printf("0\n");
else printf("%lld",fp(,n-));
return ;
}
S.clear();
for (int i=;i<=k;i++) S.insert(i);
for (int i=;i<=n;i++)
{
p[i].first=a[i];
p[i].second=i;
}
sort(p+,p++n);
p[n+].first=-;
for (int i=;i<=n;i++)
{
if (p[i+].first==p[i].first) e[p[i].second]=p[i+].second;
else e[p[i].second]=-;
}
int now=;
t[]=;
if (a[]<=k) S.erase(a[]);
for (int i=;i<=n;i++)
{
if (a[i]>k || !S.count(a[i])) t[i]=t[i-];
else
{
S.erase(a[i]);
while (S.empty())
{
if (a[now]<=k && (e[now]==-||e[now]>i))
{
S.insert(a[now]);
}
now++;
}
t[i]=now;
}
}
dp[]=;
predp[]=;
predp[]=;
for (int i=;i<=n;i++)
{
// dp[t[i]-1]...dp[i-1]
dp[i]=((predp[i]-predp[t[i]-])%md+md)%md;
predp[i+]=(predp[i]+dp[i])%md;
}
printf("%lld\n",dp[n]);
return ;
}
最新文章
- robots.txt文件没错,为何总提示封禁
- R连接Mysql时,中文显示为问号的解决方案
- VxWorks 6.9 内核编程指导之读书笔记 -- VxWorks kernel application (一)
- 你必须知道的.NET
- UVa 307 - Sticks
- 得到指定进程PID
- Objective-C中的copy协议
- Visual Studio 启动加速
- 15个提高编程技巧的JavaScript工具
- HDU - 2276 Kiki &;amp; Little Kiki 2
- eclipse 代码清理 代码格式化 代码凝视
- Stopwatch计时器、秒表 C#
- Java入门第二季第一章类和对象知识点
- iOS 之 二维码生成与扫描(LBXScan)
- Unity3D常用 API 之实例化与销毁
- luoguP1379 八数码难题[启发式搜索]
- linux memcached Session共享
- Mapreduce数据分析实例
- hadoop fs 获取文件大小
- FastDFS配置 ***
热门文章
- (数据科学学习手札01)Python与R基本数据结构之异同
- 杭电 1003 Max Sum (动态规划)
- SPFA算法(2) POJ 1511 Invitation Cards
- “Code First Migrations ”工具【转】
- java中array,arrayList,iterator;
- centos linux 因别名问题引起的麻烦及解决技巧
- c++ combination by next_permutation
- 关于transition动画下,如果有fixed元素,渲染的奇葩问题
- rails 中 preload、includes、Eager load、Joins 的区别
- 配置cas可外网访问