Gym101801ABCDEF--Tishreen-CPC 2018

Tishreen-CPC 2018


题目链接:http://codeforces.com/gym/101801

A. Can Shahhoud Solve it

Problem:判断S>=D

Solution: 水题

Code:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int t,s,d;
int main(){
	scanf("%d",&t);
	while(t--){	
		scanf("%d%d",&s,&d);
		if(s>=d) cout<<"YES"<<endl;
		else cout<<"NO"<<endl;
	}
	return 0;
} 

B. Defeat the Monsters

Problem: 每次至多消掉3个数的同一公因数,问最少需要多少次使所有数变为1

Solution: 因数分解,记录所有因子的个数,每3个加1次

Code:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=100005;
int t,n,a,cnt[maxn];
ll ans=0;
void f(int temp) {
	for(int i=2; i*i<=temp; i++) {
		if(temp%i==0) {
            if(cnt[i]==0) ans++;
				cnt[i]++;
			if(cnt[i]==3) cnt[i]=0;
			while(temp%i==0) {
				temp/=i;
			}
		}
	}
	if(temp!=1) {
        if(cnt[temp]==0) ans++;
			cnt[temp]++;
		if(cnt[temp]==3) cnt[temp]=0;
	}
}
int main() {
	scanf("%d",&t);
	while(t--) {
		ans=0;
		memset(cnt,0,sizeof(cnt));
		scanf("%d",&n);
		for(int i=1; i<=n; i++) {
			scanf("%d",&a);
			f(a);
		}
        cout<<ans<<endl;
	}
	return 0;
}

C. UCL Game Night

Problem:给定行列n,m,找最大的子阵面积,使其中1的个数<=K

Solution: 二维前缀和,状态转移方程
d p [ i ] [ j ] = d p [ i − 1 ] [ j ] + d p [ i ] [ j − 1 ] − d p [ i − 1 ] [ j − 1 ] + a [ i ] [ j ] dp[i][j]=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1]+a[i][j] dp[i][j]=dp[i1][j]+dp[i][j1]dp[i1][j1]+a[i][j]
求子阵的和<=k的最大值
S = d p [ i ] [ j ] + d p [ i − 1 ] [ j − 1 ] − d p [ i − 1 ] [ j ] − d p [ i ] [ j − 1 ] S=dp[i][j]+dp[i-1][j-1]-dp[i-1][j]-dp[i][j-1] S=dp[i][j]+dp[i1][j1]dp[i1][j]dp[i][j1]
Code

#include<bits/stdc++.h>
using namespace std;
int n,m,k,T,a[105][105],dp[105][105],ans;
int main() {
	scanf("%d",&T);
	while(T--) {
		scanf("%d%d%d",&n,&m,&k);
		ans=0;
		memset(dp,0,sizeof(dp));
		for(int i=1; i<=n; i++) {
			for(int j=1; j<=m; j++) {
				scanf("%d",&a[i][j]);
				dp[i][j]=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1]+a[i][j];
			}
		}
//		for(int i=1; i<=n; i++) {
//			for(int j=1; j<=m; j++) {
//				cout<<dp[i][j]<<" ";
//			}
//			cout<<endl;
//		}
		for(int i=1; i<=n; i++) {
			for(int j=1; j<=m; j++) {
				for(int r=i; r<=n; r++) {
					for(int c=j; c<=m; c++) {
						if(dp[r][c]+dp[i-1][j-1]-dp[r][j-1]-dp[i-1][c]<=k) {//任意子阵的和
							ans=max(ans,(r-i+1)*(c-j+1));
						}
					}
				}
			}
		}
		printf("%d\n",ans);
	}
	return 0;
}
/*
1
5 5 5
1 0 1 0 1
0 1 0 1 0
0 0 0 0 0
0 1 0 0 0
1 0 1 1 1
*/

D. Police Stations

Problem:至多建K个警局,其中每个警局有参数:

(1)P:警局离市中心距离

(2) A:警局管制范围[P-A,P+A] (该范围内不能再有其他警局)

(3) C:建造后,增加的安全度的值

(4) X: 相邻两个警局的安全度有限制条件:
∣ C ( i + 1 ) − C i ∣ ≥ k |C_(i+1)-C_i |≥k C(i+1)Cik
求满足如上限制条件的总体安全度的最大值

Solution: 排序递归求符合要求的安全度最大值,15s,TLE了

Code:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=10005;
ll T,n,k,p[maxn],a[maxn],c[maxn],x[maxn],ans;
struct Police{
	ll p,a,c,x;
}v[maxn];
bool cmp(Police a,Police b){
	return a.p<b.p;
}
ll fun(ll pr,ll temp){
	if(!temp) return 0;
	if(pr==n) return 0;
	ll cnt=0;
	for(int i=pr+1;i<=n;i++){
		if(v[i].p-v[i].a<=v[pr].p||v[pr].p+v[pr].a>=v[i].p) continue;//限制条件2
		if(abs(v[i].c-v[pr].c)<v[i].x) continue;//限制条件4
		cnt=max(cnt,fun(i,temp-1)+v[i].c);
	}
	 return cnt;
}
int main(){
	scanf("%lld",&T);
	while(T--){
		ans=0;
		scanf("%lld%lld",&n,&k);
		for(int i=1;i<=n;i++) scanf("%lld",&v[i].p);
		for(int i=1;i<=n;i++) scanf("%lld",&v[i].a);
		for(int i=1;i<=n;i++) scanf("%lld",&v[i].c);
		for(int i=1;i<=n;i++) scanf("%lld",&v[i].x);
		sort(v+1,v+n+1,cmp);
        for(int i=1;i<=n;i++){
        	ans=max(ans,fun(i,k-1)+v[i].c);
		}
		printf("%lld\n",ans);
	}
	return 0;
}
/*
1
3 2
1 5 9
3 3 4
1 3 6
2 2 2

==7
*/

E. Create Your Own Nim Game

Problem:给定N个石头,求方案数,要求先手必赢

Solution: 根据题意,先手赢要求x不为0
X = S 1 ( x o r ) S 2 ( x o r ) . . . ( x o r ) S M X = S_1 (xor) S_2 (xor) ... (xor) S_M X=S1(xor)S2(xor)...(xor)SM
dp [i] [j^k]: i 枚石头,X=j^k的符合要求的方案数,,有转移方程:
d p [ i ] [ j ( x o r ) k ] + = d p [ i − j ] [ k ] , j = 1... i ; ; k = 0 , 1 , 2... i , dp[i][j(xor)k]+=dp[i-j][k],j=1...i;;k=0,1,2...i, dp[i][j(xor)k]+=dp[ij][k],j=1...i;;k=0,1,2...i,
Code:

#include<bits/stdc++.h>
using namespace std;
const int MOD=1e9+7;
typedef long long ll;
ll dp[105][105],ans;
int n,T; 
int main(){
    dp[0][0]=1;
    for(int i=1;i<=100;i++){
    	for(int j=1;j<=i;j++){
    		for(int k=0;k<=i;k++){
    			dp[i][j^k]=(dp[i][j^k]+dp[i-j][k])%MOD;
			}
		}
	}
//	for(int i=1;i<=100;i++){
//		for(int j=1;j<=i;j++){
//			cout<<dp[i][j]<<" ";
//		}
//		cout<<endl;
//	}
	scanf("%d",&T);
	while(T--){
		scanf("%d",&n);
		ans=0;
		for(int i=1;i<=n;i++){
			ans=(ans+dp[n][i])%MOD;
		}
		printf("%lld\n",ans);
	}
	return 0;
}

F. Nim Cheater

Problem: M堆石头各Si个,问最少需要拿几个石头可以赢得比赛

Solution: 根据题意x=0后手赢,否则先手赢
X = S 1 x o r S 2 x o r . . . x o r S M X = S1 xor S2 xor ... xor SM X=S1xorS2xor...xorSM
暴力全部xor一遍;X=0,理想状况,拿一个赢;x!=0,一定赢

Code:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int t,m,s,ans;
int main(){
	scanf("%d",&t);
	while(t--){	
		scanf("%d%d",&m,&ans);
		for(int i=2;i<=m;i++){
			scanf("%d",&s);
			ans^=s;
		}
		if(ans)  cout<<0<<endl;
		else cout<<1<<endl;
	}
	return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值