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;
}
}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\n",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!\)的末尾零的个数。

\(n\leq10^{18},\ b\leq10^{12}\)。

\(Solution\)

经典问题。。所以也是一道能搜到的题。。

如果\(d=10\),就是求\(n!\)有多少个\(2\)和\(5\)的因子\(c_2,c_5\),答案是\(\min\{c_2,c_5\}\),不难理解。

如果\(d\neq10\),同样对\(d\)质因数分解,令\(d=\prod_{i=1}^kp_i^{a_i},\ a_i\neq0\),依次求出\(n!\)中有多少个\(p_i\),记为\(c_i\),答案就是\(\min_{i=1}^k\{c_i\}\)。

求\(n!\)中质因子\(p\)的个数的公式:$$f(n)=\left\lfloor\frac{n}{p}\right\rfloor +\left\lfloor\frac{n}{p^2}\right\rfloor +\left\lfloor\frac{n}{p^3}\right\rfloor +\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\n",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\n",ans); return 0;
}

D.Flood Fill(区间DP)

刚开始一看\(O(n^2)\),就想枚举起点然后模拟。。(mdzz)

无脑区间DP。。

\(f[i][j][0/1]\)表示合并完\(i\sim j\)区间,现在颜色是\(c_i/c_j\)的最小花费。转移特判一下即可。

或者先去掉相邻的重复元素,直接\(f[i][j]\)表示合并完\(i\sim 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\n",std::min(f[1][n][0],f[1][n][1])); return 0;
}

E.Arithmetic Progression(交互 二分 随机化)

首先通过操作二可以二分出最大值。

然后剩下\(30\)次操作一能干什么呢。。只能帮我们确定出数列中有某些数,那能做的好像就是随机确定\(30\)个数。

等差数列中任意两个数作差可以得到\(x\cdot d\),把确定出的数两两作差然后对差求\(\gcd\),是有可能得到真正的\(d\)的。

正确概率是多少呢,感觉挺高的。。然后有最大值有公差,就做完了。

官方题解中对正确概率有证明,大约是\(1.86185\times10^{-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\n",id[p]), Flush();
std::swap(id[p],id[n]);//不这么写也行 差别不大 无所谓啦
return read();
}
inline int Query2(int x)
{
printf("> %d\n",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\n",mx-(n-1)*d,d), Flush(); return 0;
}

F.Please, another Queries on Array?(线段树 欧拉函数)

\(Description\)

给定长为\(n\)的序列\(A_i\),要求支持两种操作:

  1. \(l,r,v\),区间\([l,r]\)乘一个数\(v\);
  2. \(l,r\),输出\(\varphi(\prod_{i=l}^rA_i)\)。

    \(n\leq4\times10^5,\ q\leq2\times10^5,\ A_i,v\leq300\)。

\(Solution\)

听旁边dalao讨论好像特别可做,扔掉E看F。

忘了欧拉函数怎么求。。去百度百科看了下,发现这不是线段树裸题吗。。



设\(\prod_{i=l}^rA_i=n=\prod_{i=1}^kp_i^{a_i}\),那\(\varphi(n)=\prod_{i=1}^kp_i^{a_i}\frac{p_i-1}{p_i}=n\prod_{i=1}^k\frac{p_i-1}{p_i}\)。

\(k\)是\(300\)以内质数个数,就是\(62\)。所以我们维护一个区间乘积、区间某个质因子是否出现过就完了。

后者可以用bitset维护,或者因为只有\(62\)个用long long也行。

复杂度\(O(q(\log^2n+62))\)(区间乘积竟然第一次写...要快速幂所以多个\(\log\)。但是有方法可以去掉快速幂的复杂度,见这一题)。

//1809ms	42100KB
#include <cstdio>
#include <cctype>
#include <bitset>
#include <cstring>
#include <algorithm>
#define gc() getchar()
#define mod 1000000007
typedef long long LL;
const int N=4e5+5,M=301,LIM=62;
const int P[LIM]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293};
const int ref[M]={0,0,0,1,0,2,0,3,0,0,0,4,0,5,0,0,0,6,0,7,0,0,0,8,0,0,0,0,0,9,0,10,0,0,0,0,0,11,0,0,0,12,0,13,0,0,0,14,0,0,0,0,0,15,0,0,0,0,0,16,0,17,0,0,0,0,0,18,0,0,0,19,0,20,0,0,0,0,0,21,0,0,0,22,0,0,0,0,0,23,0,0,0,0,0,0,0,24,0,0,0,25,0,26,0,0,0,27,0,28,0,0,0,29,0,0,0,0,0,0,0,0,0,0,0,0,0,30,0,0,0,31,0,0,0,0,0,32,0,33,0,0,0,0,0,0,0,0,0,34,0,35,0,0,0,0,0,36,0,0,0,0,0,37,0,0,0,38,0,0,0,0,0,39,0,0,0,0,0,40,0,41,0,0,0,0,0,0,0,0,0,42,0,43,0,0,0,44,0,45,0,0,0,0,0,0,0,0,0,0,0,46,0,0,0,0,0,0,0,0,0,0,0,47,0,0,0,48,0,49,0,0,0,50,0,0,0,0,0,51,0,52,0,0,0,0,0,0,0,0,0,53,0,0,0,0,0,54,0,0,0,0,0,55,0,0,0,0,0,56,0,57,0,0,0,0,0,58,0,0,0,59,0,60,0,0,0,0,0,0,0,0,0,61};
//为什么const之后慢了不少= = inline int read();
struct Segment_Tree
{
#define ls rt<<1
#define rs rt<<1|1
#define lson l,m,ls
#define rson m+1,r,rs
#define S N<<2
int val[S],tag[S];
LL now,Ans,f[S],tagf[S];
#undef S
#define Upd(rt,v,l,vf) val[rt]=1ll*val[rt]*FP(v,l)%mod, tag[rt]=1ll*tag[rt]*v%mod, f[rt]|=vf, tagf[rt]|=vf
#define Update(rt) f[rt]=f[ls]|f[rs], val[rt]=1ll*val[ls]*val[rs]%mod
inline int FP(int x,int k)
{
int t=1;
for(; k; k>>=1,x=1ll*x*x%mod)
if(k&1) t=1ll*t*x%mod;
return t;
}
void Build(int l,int r,int rt)
{
tag[rt]=1;
if(l==r)
{
int v=read(); val[rt]=v;
for(int i=0; i<LIM&&P[i]*P[i]<=v; ++i)
if(!(v%P[i]))
{
f[rt]|=1ll<<i, v/=P[i];//1ll!!!
while(!(v%P[i])) v/=P[i];
}
if(v!=1) f[rt]|=1ll<<ref[v];
return;
}
int m=l+r>>1;
Build(lson), Build(rson), Update(rt);
}
inline void PushDown(int rt,int m)
{
int l=ls,r=rs;
Upd(l,tag[rt],m-(m>>1),tagf[rt]), Upd(r,tag[rt],m>>1,tagf[rt]), tag[rt]=1, tagf[rt]=0;
}
void Modify(int l,int r,int rt,int L,int R,int v)
{
if(L<=l && r<=R)
{
Upd(rt,v,r-l+1,now);
return;
}
if(tag[rt]!=1) PushDown(rt,r-l+1);
int m=l+r>>1;
if(L<=m) Modify(lson,L,R,v);
if(m<R) Modify(rson,L,R,v);
Update(rt);
}
int Query(int l,int r,int rt,int L,int R)
{
if(L<=l && r<=R) return Ans|=f[rt],val[rt];
if(tag[rt]!=1) PushDown(rt,r-l+1);
int m=l+r>>1;
if(L<=m)
if(m<R) return 1ll*Query(lson,L,R)*Query(rson,L,R)%mod;
else return Query(lson,L,R);
return Query(rson,L,R);
}
}T; 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;
}
//void Init(int n)
//{
// static int P[N];
// static bool notP[M];
// for(int i=2,cnt=0; i<=n; ++i)
// {
// if(!notP[i]) ref[i]=cnt, P[cnt++]=i;
// for(int j=0; j<cnt && i*P[j]<=n; ++j)
// {
// notP[i*P[j]]=1;
// if(!(i%P[j])) break;
// }
// }
//}
inline char GetOpt()
{
register char c;
while(!isalpha(c=gc()));
return c;
} int main()
{
static int inv[N],coef[N];
// Init(M-1);
inv[1]=1;
for(int i=2; i<M; ++i) inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
for(int i=0; i<LIM; ++i) coef[i]=1ll*(P[i]-1)*inv[P[i]]%mod; int n=read(),q=read();
T.Build(1,n,1);
while(q--)
{
if(GetOpt()=='T')
{
T.Ans=0;
int l=read(),r=read(),val=T.Query(1,n,1,l,r);
for(int i=0; i<LIM; ++i)
if(T.Ans>>i&1) val=1ll*val*coef[i]%mod;
printf("%d\n",val);
}
else
{
int l=read(),r=read(),x=read(),v=x;
LL now=0;
for(int i=0; i<LIM&&P[i]*P[i]<=v; ++i)
if(!(v%P[i]))
{
now|=1ll<<i, v/=P[i];
while(!(v%P[i])) v/=P[i];
}
if(v!=1) now|=1ll<<ref[v];
T.now=now, T.Modify(1,n,1,l,r,x);
}
}
return 0;
}

Codeforces Round #538 (Div. 2)的更多相关文章

  1. Codeforces Round #538 (Div. 2) (A-E题解)

    Codeforces Round #538 (Div. 2) 题目链接:https://codeforces.com/contest/1114 A. Got Any Grapes? 题意: 有三个人, ...

  2. Codeforces Round #538 (Div. 2) (CF1114)

    Codeforces Round #538 (Div. 2) (CF1114)   今天昨天晚上的cf打的非常惨(仅代表淮中最低水平   先是一路缓慢地才A掉B,C,然后就开始杠D.于是写出了一个O( ...

  3. Codeforces Round #538 (Div. 2) C. Trailing Loves (or L'oeufs?) (分解质因数)

    题目:http://codeforces.com/problemset/problem/1114/C 题意:给你n,m,让你求n!换算成m进制的末尾0的个数是多少(1<n<1e18    ...

  4. Codeforces Round #538 (Div. 2) F 欧拉函数 + 区间修改线段树

    https://codeforces.com/contest/1114/problem/F 欧拉函数 + 区间更新线段树 题意 对一个序列(n<=4e5,a[i]<=300)两种操作: 1 ...

  5. Codeforces Round #538 (Div. 2) E 随机数生成

    https://codeforces.com/contest/1114/problem/E 题意 交互题,需要去猜一个乱序的等差数列的首项和公差,你能问两种问题 1. 数列中有没有数比x大 2. 数列 ...

  6. Codeforces Round #538 (Div. 2) C 数论 + 求b进制后缀零

    https://codeforces.com/contest/1114/problem/C 题意 给你一个数n(<=1e8),要你求出n!在b进制下的后缀零个数(b<=1e12) 题解 a ...

  7. Codeforces Round #538 (Div. 2) D. Flood Fill 【区间dp || LPS (最长回文序列)】

    任意门:http://codeforces.com/contest/1114/problem/D D. Flood Fill time limit per test 2 seconds memory ...

  8. Codeforces Round #538 (Div. 2) CTrailing Loves (or L'oeufs?)

    这题明白的意思就是求n!在b进制下的后缀零的个数. 即最大的n!%(b^k)==0的k的值.我们需要将如果要构成b这个数,肯定是由一个个质因子相乘得到的.我们只需要求出b的质因子,然后分析n!中可以组 ...

  9. Codeforces Round #538 (Div. 2)D(区间DP,思维)

    #include<bits/stdc++.h>using namespace std;int a[5007];int dp[5007][5007];int main(){    int n ...

随机推荐

  1. Android学习基础部分

    今天是放寒假的第四天,这几天加上放假前总共弄了一些Android编程的基础部分,比如下载sdk.配置环境.下载Eclipse的插件(ADT).下载Android Studio.VirtualBox.G ...

  2. Mac OS X10.8.3-bash基本命令失效后的修复

    -bash基本命令都失败了. 比如: -bash: ls :command not found   顿时心都凉了. 想要找到.bash_profile文件也不是那么容易的.     step1. 在t ...

  3. UPC 6616 Small Mulitple

    D - Small Multiple 题目传送门 Time limit : 2sec / Memory limit : 256MB Score : 700 points Problem Stateme ...

  4. 使用Docker方式运行Mysql(MariaDB)

    两者差不多.我使用的是MariaDB. 下面的docker命令,挂了数据,配置,映射了端口,指定了root密码,服务端编码. 蛮快的! docker run \ --name mariadb \ -v ...

  5. checkbox选中相关问题总结

    html: <input type="checkbox" name="fruit" id="apple">苹果 <inpu ...

  6. java传值和传引用区别

    1. 在java中所有的参数都是传值的,引用符号&的传递是C++中才有的:2. 在java传参中,基本类型(byte--short--int--long--float--double--boo ...

  7. [转]sqlplus /nolog 出错解决 SP2-0667: Message file sp1<lang>.msb not found SP2-0750: You may need to set ORACLE_HOME to your Oracle software directory

    http://techxploration.blogspot.com/2012/01/resolving-sp2-0750-you-may-need-to-set.html Resolving SP2 ...

  8. 1900型USB接口扫描枪设置虚拟串口模式提升扫描速度

    在使用扫描枪的过程中,发现扫描二维码速度比较慢,不到100个字符,花了大概2-3秒的时间才完成显示,这个速度不能忍受啊.通过度娘,说是可以将USB键盘模式接收字符转换成虚拟串口接收,这样可以大大提高速 ...

  9. Python 事件驱动与异步IO

    一.事件驱动编程是一种编程范式,这里程序的执行流由外部事件来决定.它的特点是包含一个事件循环,当外部事件发生时使用回调机制来出发相应的处理.另外两种常见的编程范式是(单线程)同步以及多线程编程. 1. ...

  10. react添加样式的四种方法

    React给添加元素增加样式 第一种方法: <!DOCTYPE html> <html lang="en"> <head> <meta c ...