• [CF1501] Codeforces Round #707 (Div. 2, based on Moscow Open Olympiad in Informatics)


    Problemsimg

    # Name
    A Alexey and Train Submit Add to favourites img x5859
    B Napoleon Cake Submit Add to favourites img x5579
    C Going Home Submit Add to favourites img x1506
    D Two chandeliers Submit Add to favourites img x95
    E Matrix Sorting Submit Add to favourites img x3
    F Tiles for Bathroom Submit Add to favourites img x1

    这场比赛的时间就很神奇。

    A Alexey and Train

    模拟题

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    
    using namespace std;
    typedef long long LL;
    typedef unsigned long long ULL;
    
    const int N=1e5+5;
    
    int T,n;
    int a[N],b[N],tm[N];
    
    int main()
    {
    //	freopen("1.in","r",stdin);
    	int i;
    	
    	scanf("%d",&T);
    	while(T--) {
    		scanf("%d",&n);
    		for(i=1;i<=n;i++) scanf("%d%d",&a[i],&b[i]);
    		for(i=1;i<=n;i++) scanf("%d",&tm[i]);
    		
    		int ans=0;
    		for(i=1;i<=n;i++) {
    			ans=ans+tm[i]+a[i]-b[i-1];
    			if(i==n) break;
    			ans=max(ans+(b[i]-a[i]+1)/2,b[i]);
    		}
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    

    B Napoleon Cake

    差分一下就可以了。

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    
    using namespace std;
    typedef long long LL;
    typedef unsigned long long ULL;
    
    const int N=2e5+5;
    
    int T,n;
    int a[N],c[N];
    
    int main()
    {
    //	freopen("1.in","r",stdin);
    	int i;
    	
    	scanf("%d",&T);
    	while(T--) {
    		scanf("%d",&n);
    		for(i=0;i<=n;i++) c[i]=0;
    		for(i=1;i<=n;i++) scanf("%d",&a[i]);
    		for(i=1;i<=n;i++) c[max(i-a[i]+1,1)]++,c[i+1]--;
    		for(i=1;i<=n;i++) c[i]+=c[i-1];
    		for(i=1;i<=n;i++) printf("%d ",(c[i]>0));
    		puts("");
    	}
    	return 0;
    }
    

    C Going Home

    题意,给定 (a_1...a_n) ,求出四个不同的下标满足 (x,y,z,w) 满足 (a_x+a_y=a_z+a_w)

    (n le 10^5,max a le 2.5 imes 10^6)

    很有意思的一道题。

    (a_x-a_z=a_w-a_y)

    刚开始我还想着用 DS 维护,发现不大行。

    于是盲猜答案上界不会很大,乱证一下好像可以 (le sqrt{max a})

    于是暴力即可。

    特判掉 出现次数 (ge 2) 的情况。

    只要跑不死,就往死里跑。要死跑不完,就是 NO ANSWER。

    #include<ctime>
    #include<vector>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    
    using namespace std;
    typedef long long LL;
    typedef unsigned long long ULL;
    typedef pair<int,int> PII;
    
    const int N=5e6+5;
    
    int n,m;
    int a[N],c[N];
    
    int main()
    {
    //	freopen("1.in","r",stdin);
    	int i,j;
    	int x;
    	
    	scanf("%d",&n);
    	for(i=1;i<=n;i++) scanf("%d",&a[i]),m=max(m,a[i]);
    	for(i=1;i<=n;i++) c[a[i]]++;
    	
    	vector<int> v;
    	for(i=1;i<=m;i++) {
    		if(c[i]>=4) {
    			puts("YES");
    			for(j=1,x=0;j<=n && x<4;j++) 
    				if(a[j]==i) printf("%d ",j),x++;
    			return 0;
    		}
    		else if(c[i]>=2) v.push_back(i);
    	}
    	if(v.size()>=2) {
    		vector<int> ans;
    		for(i=0;i<2;i++) 
    			for(j=1,x=0;j<=n && x<2;j++) 
    				if(a[j]==v[i]) x++,ans.push_back(j);
    				
    		swap(ans[0],ans[2]);
    		puts("YES");
    		for(i=0;i<4;i++) printf("%d ",ans[i]);
    		return 0;
    	}
    	
    	for(i=1;i<=n;i++) c[a[i]]=i;
    	if(v.size()==1) {
    		for(i=1;v[0]-i>=1 && i+v[0]<=m;i++) {
    			if(c[v[0]-i] && c[v[0]+i]) {
    				puts("YES");
    				printf("%d %d ",c[v[0]-i],c[v[0]+i]);
    				for(j=1,x=0;j<=n && x<2;j++) 
    					if(a[j]==v[0]) printf("%d ",j),x++;
    				return 0;
    			}
    		}	
    	}
    	
    	vector<PII> ans;
    	for(i=1;i<=m && clock()<=1.8*CLOCKS_PER_SEC;i++) {
    		ans.clear();
    		for(j=1;j<=n;j++) {
    			if(c[a[j]]==j && a[j]>i && c[a[j]-i]) 
    				ans.push_back(PII(c[a[j]-i],j));
    		}
    		sort(ans.begin(),ans.end());
    		if(ans.size()>=3) {
    			puts("YES");
    			vector<int> pos;
    			pos.push_back(ans[0].first),pos.push_back(ans[0].second);
    			if(ans[1].first==ans[0].second) 
    				pos.push_back(ans[2].first),pos.push_back(ans[2].second);
    			else pos.push_back(ans[1].first),pos.push_back(ans[1].second);
    			swap(pos[0],pos[2]);
    			printf("%d %d %d %d
    ",pos[0],pos[1],pos[2],pos[3]);
    			return 0;
    		}
    		else if(ans.size()==2 && ans[1].first!=ans[0].second) 
    			return printf("YES
    %d %d %d %d
    ",ans[0].first,ans[1].second,ans[0].second,ans[1].first)&0;
    	} 
    	puts("NO");
    	return 0;
    }
    

    D Two chandeliers

    很明显的周期性质。

    思路:先求出 一个周期几次 diff , 然后二分求剩下的周期。

    Part 1 一个周期几次 diff

    (T=lcm(n,m))

    本题有一个很重要的性质,就是 (a_i) 两两不同, (b_j) 两两不同,于是相同的位置就是可枚举的。

    而不同的次数就是 (T-) 相同的次数。

    这里不妨假设 下标从 (0) 开始,假设 (a_i=b_j) ,则贡献的位置 (x) 满足

    [x=i pmod n \ x=j pmod m ]

    根据中国剩余定理,(x)([0,lcm(n,m))) 有至多一解,并且若有解,周期为 (lcm(n,m)=T)。用 excrt 合并即可。

    由于对于每个 (a_i) 至多有一个 (b_j) 与之相同,并且至多有一解,故在一个周期内至多有 (min(n,m)) 个解。求出 这些解,Part 1 就做完了。

    Part 2 二分求剩下的周期

    不妨把 Part 1 位置存在 vector 里,则再经过 (day) 天的 diff 数就是

    [day-sum_{i=0}^{v.size()-1}[v[i] le day] ]

    sort 一下,用 upper_bound 可以 (mathcal O(log n)) 求。

    总的时间复杂度 (假设 (n,m) 同阶): (mathcal O(nlog n+log^2 n))

    Code:

    注意如果最后一个周期是完整的,要特判掉。

    #include<vector>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    
    using namespace std;
    typedef long long LL;
    typedef unsigned long long ULL;
    
    const int N=1e6+5;
    
    LL muler(LL x,LL k,LL MOD)
    {
    	LL res=0; x=(x%MOD+MOD)%MOD; k=(k%MOD+MOD)%MOD; 
    	while(k) {
    		if(k&1) res=(res+x)%MOD;
    		x=(x+x)%MOD; k>>=1;
    	}
    	return res%MOD;
    }
    
    LL power(LL x,LL k,LL MOD)
    {
    	LL res=1; x%=MOD;
    	while(k) {
    		if(k&1) res=muler(res,x,MOD);
    		x=muler(x,x,MOD); k>>=1;
    	}
    	return res%MOD;
    }
    
    LL exgcd(LL a,LL b,LL& x,LL& y)
    {
    	if(b==0) {
    		x=1; y=0;
    		return a;	
    	}
    	LL z=exgcd(b,a%b,y,x);
    	y-=a/b*x;
    	return z;
    }
    
    LL inv(LL x,LL p) 
    {
    	LL y,z; exgcd(x,p,y,z);
    	return (y%p+p)%p;  
    }
    
    LL excrt(int n,LL b[],LL a[])
    {
    	LL m=a[1],ans=b[1];
    	for(int i=2;i<=n;i++) {
    		LL y,z,d=exgcd(m,a[i],y,z);
    		if((b[i]-ans)%d!=0) return -1;
    		y=muler(y,(b[i]-ans)/d,a[i]/d);
    		
    		ans+=y*m;
    		m=a[i]/d*m;
    		ans=(ans%m+m)%m;
    	}
    	return ans;
    }
    
    LL gcd(LL a,LL b) 
    {
    	if(b==0) return a;
    	else return gcd(b,a%b);
    }
    
    LL lcm(LL a,LL b) { return a/gcd(a,b)*b; }
    
    int n,m;
    LL kth;
    int a[N],b[N],c[N];
    LL A[N],B[N];
    vector<LL> v;
    
    LL calc(LL day) 
    {
    //	cerr<<day<<" "<<day-(upper_bound(v.begin(),v.end(),day)-v.begin())<<endl;
    	if(day<=0) return 0;
    	else return day-(upper_bound(v.begin(),v.end(),day)-v.begin());
    }
    
    int main()
    {
    //	freopen("1.in","r",stdin);
    	int i,j;
    	LL x;
    	
    	scanf("%d%d%lld",&n,&m,&kth);
    	for(i=0;i<n;i++) scanf("%d",&a[i]);
    	for(i=0;i<m;i++) scanf("%d",&b[i]);
    	memset(c,-1,sizeof c);
    	for(i=0;i<n;i++) c[a[i]]=i;
    	for(i=0;i<m;i++) {
    		if(~c[b[i]]) {
    			j=c[b[i]];
    			A[1]=n; A[2]=m;
    			B[1]=j; B[2]=i;
    			x=excrt(2,B,A);
    			if(x==-1) continue;
    			v.push_back(x+1);
    //			cerr<<x<<endl;
    		}
    	}
    	sort(v.begin(),v.end());
    	LL times=lcm(n,m)-v.size();
    	LL turns=(kth-1)/times;
    	kth-=turns*times;
    	
    	LL L=-1,R=lcm(n,m),mid;
    	while(L+1<R) {
    		mid=(L+R)>>1;
    		if(calc(mid)>=kth) R=mid;
    		else L=mid;
    	}
    	printf("%lld
    ",turns*lcm(n,m)+R);
    	return 0;
    }
    

    E,F 不会 wtcl:)

  • 相关阅读:
    数组和矩阵问题
    Memcached安装以及PHP的调用
    php函数ob_start()、ob_end_clean()、ob_get_contents()
    Nginx
    电影大全 API接口
    找电影资源最强攻略,知道这些你就牛B了!
    CSS3 图片旋转
    curl网站开发指南
    Redis 集群方案
    从12大技巧、30个案例、99个模板谈怎么写标题
  • 原文地址:https://www.cnblogs.com/cjl-world/p/14530823.html
Copyright © 2020-2023  润新知