https://codeforces.com/problemset/problem/1371/E1
思路:其实比较关键的是开始都去算这个具体的f(x)了,但是肯定会挺大的,而且没有模数。
可以发现当x大于max(a[i]),就是无穷大了。n!必然有一个(p<=n)的因子。
所以上界在2000
可以暴力。
考虑怎么处理这个f(x)能否被p整除。
乘法原理:
假设对1个初始的糖果数量x,对手糖果数量小于等于他的人数为v。则第一个位置有v种选择。
接着下一次时当前有(x+1)枚糖果,糖果数小于等于(x+1)的敌人数量为:v+(糖果数为x+1)的敌人数量。
又由于第一个位置排列时用掉一个,则第二个位置可填的种类数为:v+(糖果数为x+1)的敌人数量 - 1。
第3个位置可排列种类数则为:v+(糖果数为x+1的敌人数量)+ (糖果数为x+2的敌人数量)- 2。……
以此类推,以乘法原理记录种类数f(x)即可。由于只关注f(x)是否为p的倍数,故只需要模拟过程中判断乘数是否为p。
于是每次二分一下当前可放敌人数量。
#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=2e3+100;
typedef long long LL;
inline LL read(){LL x=0,f=1;char ch=getchar(); while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;}
LL a[maxn];
int main(void){
cin.tie(0);std::ios::sync_with_stdio(false);
LL n,p;cin>>n>>p;
for(LL i=1;i<=n;i++) cin>>a[i];
sort(a+1,a+1+n);
vector<LL>v;
for(LL x=a[n]+1-n;x<=a[n];x++){
LL cnt=0;bool flag=1;
for(LL j=1;j<=n;j++){
LL pos=upper_bound(a+1,a+1+n,x+cnt)-a-1;///找到第一个大于的然后-1
LL res=pos-cnt;
if(res%p==0){
flag=0;
break;
}
cnt++;
}
if(flag){
v.push_back(x);
}
}
cout<<v.size()<<"\n";
for(auto i:v){
cout<<i<<" ";
}
cout<<"\n";
return 0;
}