zoukankan      html  css  js  c++  java
  • 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;
    	}
    }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?(线段树 欧拉函数)

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

    1. (l,r,v),区间([l,r])乘一个数(v)
    2. (l,r),输出(varphi(prod_{i=l}^rA_i))
      (nleq4 imes10^5, qleq2 imes10^5, A_i,vleq300)

    (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}=nprod_{i=1}^kfrac{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
    ",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;
    }
    
  • 相关阅读:
    2013 Multi-University Training Contest 6 部分解题报告
    2013 Multi-University Training Contest 5 部分解题报告
    Codeforces Round #195 (Div. 2) 解题报告
    (转) tarjan算法
    重装SQLServer2008
    关于此博客园及其美化
    矩阵乘法
    CSP-S2019部分题解
    二维偏序
    [BOI2003]团伙
  • 原文地址:https://www.cnblogs.com/SovietPower/p/10361309.html
Copyright © 2011-2022 走看看