Codeforces Round #538 (Div. 2)
Posted sovietpower
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #538 (Div. 2)相关的知识,希望对你有一定的参考价值。
目录
Codeforces 1114
貌似最近平均难度最低的一场div2了...
但我没有把握住机会TAT
D题没往DP想 写模拟自闭了40多分钟...才发现是个傻逼区间DP
再多二十分钟就能调出F的傻逼错误了...
A.Got Any Grapes?
puts
的返回值原来是0。。刚开始写的return !puts("NO");
在样例上RE了一次= =
#include <set>
#include <map>
#include <cstdio>
#include <cctype>
#include <vector>
#include <cstring>
#include <algorithm>
#define pc putchar
#define gc() getchar()
typedef long long LL;
inline int read()
{
int now=0,f=1;register char c=gc();
for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
for(;isdigit(c);now=now*10+c-48,c=gc());
return now*f;
}
int main()
{
int x=read(),y=read(),z=read(),a=read(),b=read(),c=read();
if(a<x) return puts("NO"),0;
a-=x;
if(a+b<y) return puts("NO"),0;
int tot=a+b+c-y-z;
if(tot<0) return puts("NO"),0;
return puts("YES"),0;
return 0;
}
B.Yet Another Array Partitioning Task
因为可以每隔(m)个分一段,所以选出最大的(m*k)个数,每隔(m)个分一段就行了。
#include <set>
#include <map>
#include <cstdio>
#include <cctype>
#include <vector>
#include <cstring>
#include <algorithm>
#define pc putchar
#define gc() getchar()
typedef long long LL;
const int N=2e5+5;
struct Node
{
int v,p;
bool operator <(const Node &x)const
{
return v==x.v?p<x.p:v>x.v;
}
}A[N];
inline int read()
{
int now=0,f=1;register char c=gc();
for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
for(;isdigit(c);now=now*10+c-48,c=gc());
return now*f;
}
int main()
{
static int Ans[N];
static bool vis[N];
int n=read(),m=read(),K=read();
for(int i=1; i<=n; ++i) A[i]=(Node){read(),i};
std::sort(A+1,A+1+n);
LL sum=0;
for(int i=1; i<=K*m; ++i) vis[A[i].p]=1, sum+=A[i].v;
int cnt=0;
for(int i=1,t=0; i<=n; ++i)
if(vis[i] && ++t==m)
t=0, Ans[++cnt]=i;
printf("%I64d
",sum);
for(int i=1; i<cnt; ++i) printf("%d ",Ans[i]);
return 0;
}
C.Trailing Loves (or L‘oeufs?)
(Description)
给定(n,b),求(b)进制下(n!)的末尾零的个数。
(nleq10^{18}, bleq10^{12})。
(Solution)
经典问题。。所以也是一道能搜到的题。。
如果(d=10),就是求(n!)有多少个(2)和(5)的因子(c_2,c_5),答案是(min{c_2,c_5}),不难理解。
如果(d
eq10),同样对(d)质因数分解,令(d=prod_{i=1}^kp_i^{a_i}, a_i
eq0),依次求出(n!)中有多少个(p_i),记为(c_i),答案就是(min_{i=1}^k{c_i})。
求(n!)中质因子(p)的个数的公式:[f(n)=leftlfloorfrac{n}{p}
ight
floor +leftlfloorfrac{n}{p^2}
ight
floor +leftlfloorfrac{n}{p^3}
ight
floor +cdots]
实际写的时候(n)每次除以(p)即可,不需要分母不断乘(p),会爆long long
。。。
#include <set>
#include <map>
#include <cstdio>
#include <cctype>
#include <vector>
#include <cstring>
#include <algorithm>
#define pc putchar
#define gc() getchar()
typedef long long LL;
const int N=1e6+5;
inline LL read()
{
LL now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-48,c=gc());
return now;
}
LL Calc(LL x,LL y)
{
LL res=0;
for(; x; x/=y) res+=x/y;
return res;
}
int main()
{
static LL P[N];
static int tm[N];
LL n=read(),b=read();
//1
LL ans=1ll<<60;
for(int i=2; 1ll*i*i<=b; ++i)
if(!(b%i))
{
LL cnt=1; b/=i;
while(!(b%i)) b/=i, ++cnt;
ans=std::min(ans,Calc(n,i)/cnt);
}
if(b!=1) ans=std::min(ans,Calc(n,b));
printf("%I64d
",ans);
return 0;
//2
int t=0;
for(int i=2; 1ll*i*i<=b; ++i)
if(!(b%i))
{
P[++t]=i, b/=i, tm[t]=1;
while(!(b%i)) b/=i, ++tm[t];
}
if(b!=1) P[++t]=b, tm[t]=1;
ans=1ll<<60;
for(int i=1; i<=t; ++i)
{
LL cnt=0;
// for(LL x=P[i]; x<=n&&x>0; x*=P[i]) cnt+=n/x;//这么写可能直接爆longlong爆成正数啊。。。= =
for(LL x=n; x; x/=P[i]) cnt+=x/P[i];
ans=std::min(ans,cnt/tm[i]);
}
printf("%I64d
",ans);
return 0;
}
D.Flood Fill(区间DP)
刚开始一看(O(n^2)),就想枚举起点然后模拟。。(mdzz)
无脑区间DP。。
(f[i][j][0/1])表示合并完(isim j)区间,现在颜色是(c_i/c_j)的最小花费。转移特判一下即可。
或者先去掉相邻的重复元素,直接(f[i][j])表示合并完(isim j)区间的最小花费。如果(c_i=c_j),(f[i][j]=f[i+1][j-1]+1);否则(f[i][j]=min(f[i+1][j], f[i][j-1])+1)。
#include <set>
#include <map>
#include <cstdio>
#include <cctype>
#include <vector>
#include <cstring>
#include <algorithm>
#define pc putchar
#define gc() getchar()
typedef long long LL;
const int N=5005;
int A[N],f[N][N][2];
inline int read()
{
int now=0,f=1;register char c=gc();
for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
for(;isdigit(c);now=now*10+c-48,c=gc());
return now*f;
}
bool Check(int n)
{
for(int i=1; i<=n; ++i) if(A[i]!=A[1]) return 0;
puts("0");
return 1;
}
int main()
{
int n=read();
for(int i=1; i<=n; ++i) A[i]=read();
if(Check(n)) return 0;
memset(f,0x3f,sizeof f);
for(int i=1; i<=n; ++i) f[i][i][0]=f[i][i][1]=0;
for(int l=1; l<n; ++l)
for(int i=1; i+l<=n; ++i)
{
int j=i+l;
f[i][j][0]=std::min(f[i][j-1][0]+2-2*(A[i]==A[j]),std::min(f[i][j-1][1]+2-(A[j-1]==A[j])-(A[i]==A[j]),std::min(f[i+1][j][0]+1-(A[i]==A[i+1]),f[i+1][j][1]+1-(A[j]==A[i]))));
f[i][j][1]=std::min(f[i][j-1][0]+1-(A[i]==A[j]),std::min(f[i][j-1][1]+1-(A[j-1]==A[j]),std::min(f[i+1][j][0]+2-(A[i]==A[i+1])-(A[i]==A[j]),f[i+1][j][1]+2-2*(A[j]==A[i]))));
}
printf("%d
",std::min(f[1][n][0],f[1][n][1]));
return 0;
}
E.Arithmetic Progression(交互 二分 随机化)
首先通过操作二可以二分出最大值。
然后剩下(30)次操作一能干什么呢。。只能帮我们确定出数列中有某些数,那能做的好像就是随机确定(30)个数。
等差数列中任意两个数作差可以得到(xcdot d),把确定出的数两两作差然后对差求(gcd),是有可能得到真正的(d)的。
正确概率是多少呢,感觉挺高的。。然后有最大值有公差,就做完了。
官方题解中对正确概率有证明,大约是(1.86185 imes10^{-9})。
做差的时候先排序,只求出相邻两个数的差就够了,并不需要所有数两两之间作差。
#include <ctime>
#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
#define Flush() fflush(stdout)
typedef long long LL;
const int N=1e6+5;
int id[N];
inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-48,c=gc());
return now;
}
inline int Rd()
{
return rand()<<15|rand();
}
inline int Query1(int n)
{
int p=Rd()%n+1;
printf("? %d
",id[p]), Flush();
std::swap(id[p],id[n]);//不这么写也行 差别不大 无所谓啦
return read();
}
inline int Query2(int x)
{
printf("> %d
",x), Flush();
return read();
}
int main()
{
static int A[66];
srand(time(0));
int n=read();
int l=0,r=1e9,mid,mx=0,rest=60;
while(l<=r)
if(--rest,Query2(mid=l+r>>1)) mx=l=mid+1;
else r=mid-1;
for(int i=1; i<=n; ++i) id[i]=i;
int t=0; rest=std::min(rest,n);
for(int now=n; rest; --rest) A[++t]=Query1(now--);
std::sort(A+1,A+1+t), A[++t]=mx;
int d=A[2]-A[1];
for(int i=3; i<=t; ++i) if(A[i]!=A[i-1]) d=std::__gcd(d,A[i]-A[i-1]);
printf("! %d %d
",mx-(n-1)*d,d), Flush();
return 0;
}
F.Please, another Queries on Array?(线段树 欧拉函数)
以上是关于Codeforces Round #538 (Div. 2)的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #538 (Div. 2) (CF1114)
CodeForces Contest #1114: Round #538 (Div. 2)
[比赛] Codeforces Round #538 (Div. 2) solution (贪心,数学其他,二分,线段树)
Codeforces Round #538 (Div. 2) D. Flood Fill 区间dp || LPS (最长回文序列)
Codeforces Round #538 (Div. 2) E 随机数生成
[codeforces]Round #538 (Div. 2) F. Please, another Queries on Array?