ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

gym101522G~L----La Salle-Pui Ching Programming Challenge 培正喇沙編程挑戰賽 2017

2020-01-31 14:04:41  阅读:235  来源: 互联网

标签:Salle Pui La int ll ans x1 dp r1


La Salle-Pui Ching Programming Challenge 培正喇沙編程挑戰賽 2017

文章目录

G.Gravitational Tetris

**题意:**类似于俄罗斯方块,10列,给定每列剩余方块数(<=12),通过使用8种不同形状的组块,使每行全部消除

输出总共需要的组块数,以及每行每次的使用型号以及使用位置(组块摆放位置左下角所在列)

题解:因为是一定可以消除的,每个型号都是4块方块组成,10列,只需输出任意一种方案,则只需考虑一种能满足所有可能情况至少需要的消除行数。由此,可假定铺满40行(>=24且能通过1,2,3,4组合皆可;通过使用型号AG使前9列铺满40行,a[i]+4A+3G=40,求满足的一组A,G即可,然后a[i+1]+=G;(G为L字形)

通过分类讨论最后一列的方块个数(除4余2或整除4),用AG铺满38格(除4余2)或40格。对于前者再使用1个E(置于9列),两个B(置于第1,5列)。

记录使用总数,储存使用型号和位置

#include<bits/stdc++.h>
using namespace std;
int a[10],b,c,cnt=0;
vector<char>s;
vector<int>v; 
int main(){
	for(int i=0;i<10;i++){
		scanf("%d",&a[i]);
	}
	for(int i=0;i<9;i++){//前9列铺满40行
		b=(40-a[i])/4;
		for(int j=b;j>=0;j--){
			if((40-a[i]-j*4)%3==0){
				c=(40-a[i]-j*4)/3;
				b=j;
				break;
			} 
		}
		a[i+1]+=c;
		a[i]+=4*b+c*3;
		for(int j=1;j<=b;j++){
			s.push_back('A');
			v.push_back(i+1);
		}
		for(int j=1;j<=c;j++){
			s.push_back('G');
			v.push_back(i+1);
		}
		cnt+=c+b;
	}
	if(a[9]%4==0){//第10列单独讨论
		for(int i=1;i<=(40-a[9])/4;i++){
			s.push_back('A');
			v.push_back(10);
			cnt++;
		}
	}else if(a[9]%4==2){
		for(int i=1;i<=(38-a[9])/4;i++){
			s.push_back('A');
			v.push_back(10);
			cnt++;
		}
		s.push_back('E');
		v.push_back(9);
		s.push_back('B');
		v.push_back(1);
		s.push_back('B');
		v.push_back(5);
		cnt+=3;
	}
	cout<<cnt<<endl;
	for(int i=0;i<s.size();i++){
		cout<<s[i]<<" "<<v[i]<<endl;
	}
}

H.Hit!

题意:给定两圆圆心坐标、半径,输出任意一点,该点在两圆公共部分内

**题解:**已知两圆,
(xx1)2+(yy1)2=r12(xx2)2+(yy2)2=r22 (x-x_1 )^2+(y-y_1 )^2=r_1^2,,(x-x_2 )^2+(y-y_2 )^2=r_2^2 (x−x1​)2+(y−y1​)2=r12​,,(x−x2​)2+(y−y2​)2=r22​
两圆公式相减得一条直线(公共弦或切线),令其与连心线相交的点为P(在两圆相交的公共部分内)
O1P=λPO2(λ>0), O_1 P=λPO_2(这里表示长度大小,λ>0), O1​P=λPO2​(这里表示长度大小,λ>0),

λ=((x1x1)2+(y1y2)2+(r12r22))/((x1x2)2+(yy2)2(r12r22)) 其中λ=|((x_1-x_1 )^2+(y_1-y_2 )^2+(r_1^2-r_2^2 ))/((x_1-x_2 )^2+(y-y_2 )^2-(r_1^2-r_2^2 ) )| 其中λ=∣((x1​−x1​)2+(y1​−y2​)2+(r12​−r22​))/((x1​−x2​)2+(y−y2​)2−(r12​−r22​))∣

再以连心线为斜边,平行于x,y轴的直角边的三角形,通过比例线段得到该点的横纵坐标

特别的:当 λ=r1/r2 时,两圆相切,此时P点坐标
p((x1r1+x2r1)/(r1+r2),(y1r2+y2r1)/(r1+r2)) p((x_1 r_1+x_2 r_1)/(r_1+r_2 ),(y_1 r_2+y_2 r_1)/(r_1+r_2 )) p((x1​r1​+x2​r1​)/(r1​+r2​),(y1​r2​+y2​r1​)/(r1​+r2​))
(代入相切情况的坐标公式就符合所有点过了,保险起见可通过比例线段求一般坐标公式)

#include<bits/stdc++.h>
using namespace std;
int xa,ya,ra,xb,yb,rb;
int main(){
    cin>>xa>>ya>>ra>>xb>>yb>>rb;
    double r=ra+rb;
    printf("%.6lf %.6lf",(double)(xa*rb+xb*ra)/r,(double)(ya*rb+yb*ra)/r);
}

I. Inverted Signs

**题意:**一串数,定义混沌指数为相邻两数的差值总和,改变其中连续几位的符号,使得混沌指数最小, 求最小值

题解:显然若改变H[l]…H[r]的符号,混沌指数改变的只有|H[l]-H[l-1]|和|H[r+1]-H[r]|这两项

改变的大小分别为|H[i]+H[i-1]|-|H[i]-H[i-1]|

遍历找出所有负改变(使混沌数减小)的项,选取负改变最多的两项,考虑特殊情况

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1000005;
ll n,h[maxn],sum=0;
vector<ll>v;
int main() {
    scanf("%lld",&n);
    scanf("%lld",&h[1]);
    for(ll i=2; i<=n; i++) {
        scanf("%lld",&h[i]);
        sum+=abs(h[i]-h[i-1]);
        int t=abs(h[i-1]+h[i])-abs(h[i]-h[i-1]);
        if(t<0)  v.push_back(t);//负改变的项
    }
    int len=v.size();
    if(len==0) return cout<<sum,0;
    sort(v.begin(),v.end());
    if(len==1) return cout<<sum+v[0],0;
    if(len>1) return cout<<sum+v[0]+v[1],0;
}

J . Juicy Candies

**题意:**求由B个‘B’, R个‘R’,S个’S’组成的所有字符串中(相邻字母要求不同) 字典序第k小的字符串,没有:None

**题解:**定义dp [i] [b] [r] [s] 表示以b个’B’,r个’R’,s个’S’,i所代表字母开头的前缀的字符串种数(i=0表示B, 1表示R, 2表示S )

显然 dp [0] [1] [0] [0]=dp [1] [0] [1] [0]= dp [2] [0] [0] [1]=1 有状态转移方程

i=0时:dp[i] [b] [r] [s]=dp [1] [b-1] [r] [s]+dp [2] [b-1] [r] [s]

i=1时:dp[i] [b] [r] [s]=dp [0] [b] [r-1] [s]+dp [2] [b] [r-1] [s]

i=2时:dp[i] [b] [r] [s]=dp [0] [b] [r] [s-1]+dp [1] [b] [r] [s-1]

当 dp[0] [B] [R] [S]+dp [1] [B] [R] [S]+dp [2] [B] [R] [S]<K 时 不存在

找字符串时,遵循:

(1): b<B&c!=‘B’&dp[0] [B-b] [R-r] [S-s]>=K, +‘B’,K-=dp[0] [B-b] [R-r] [S-s] ,Go to (4)

(2): r<R&c!=‘R’&dp[1] [B-b] [R-r] [S-s]>=K, +‘R’,K-=dp[1] [B-b] [R-r] [S-s] Go to (4)

(3): s<S&c!=‘S’&dp[2] [B-b] [R-r] [S-s]>=K, +‘S’, K-=dp[2] [B-b] [R-r] [S-s]

(4): 更新b,r,s,c的值

#include<bits/stdc++.h>
using namespace std;
typedef long long ll; 
const ll maxn=1e18+5;
ll B,R,S,K;
ll dp[3][205][205][205];//dp[i][b][r][s]以b个B、r个R、s个S、i开头为前缀的字符串的个数 
string str; 
int main(){
	scanf("%lld%lld%lld%lld",&B,&R,&S,&K);
	dp[0][1][0][0]=dp[1][0][1][0]=dp[2][0][0][1]=1;
	for(int a=0;a<=B;a++){
		for(int b=0;b<=R;b++){
			for(int c=0;c<=S;c++){
				for(int i=0;i<3;i++){//状态转移
					if(a&&i==0) dp[i][a][b][c]+=dp[1][a-1][b][c]+dp[2][a-1][b][c];
					if(b&&i==1) dp[i][a][b][c]+=dp[0][a][b-1][c]+dp[2][a][b-1][c];
					if(c&&i==2) dp[i][a][b][c]+=dp[0][a][b][c-1]+dp[1][a][b][c-1]; 
					if(dp[i][a][b][c]>=K) dp[i][a][b][c]=maxn;
				}
			}
		}
	}
	if(dp[0][B][R][S]+dp[1][B][R][S]+dp[2][B][R][S]<K) return cout<<"None",0;//字典序第k小的字符串不存在
	ll p=-1,b=B,r=R,s=S;
	for(int i=1;i<=B+R+S;i++){
		for(int j=0;j<3;j++){
			if(j!=p){
				if(dp[j][b][r][s]>=K){
					if(b&&j==0){
						b--;
						str.push_back('B');
					}else if(r&&j==1){
						r--;
						str.push_back('R');
					}else if(s&&j==2){
						s--;
						str.push_back('S');
					}
					p=j;
					break;
				}else K-=dp[j][b][r][s];
			}
		}
	}
	cout<<str;
	return 0;
}

K .Knights

**题意:**N*M矩形,同行或同列已被占领的格子中间的所有格子都会被占领,求在给定已占领格子的基础上占领所有格子还至少需要派骑士占领多少个格子;

**题解:**4个角必须单独派骑士占领,同时4个角占领,整个矩形也被占领,所以至少需要4个

考虑特殊情况 1*1:至少1个; 一行或一列:至少两个 其他:4个 ; 扣除给定的角

#include<bits/stdc++.h>
using namespace std;
int n,m,k,x,y,cnt=0;
int main(){
	scanf("%d%d%d",&n,&m,&k);
	for(int i=1;i<=k;i++){
		scanf("%d%d",&x,&y);
		if(x==1&&y==1) cnt++;
		else if(x==1&&y==m) cnt++;
		else if(x==n&&y==1) cnt++;
		else if(x==n&&y==m) cnt++;
	}
	if(n==1&&m==1) return cout<<1-cnt,0;
	if(n==1||m==1) return cout<<2-cnt,0;
	return cout<<4-cnt,0;
}

L .Let Me Count The Ways

题意: 给定两行,分别n列,m列(n>=m), 将n+m个数放入这m+n个格子,使得数字不重复、每行前面的数比后面的数大,每列第一行的数比第二行的数大,,,,求有几种放法。对1e9+7取模

题解: 答案为第一行按照大小选取n个数C(m+n,n),减掉不符合列大小规则的数量C(n+m,n+1);

即 c(m+n,n) - C(n+m,n+1)

这里使用了快速幂逆元,Lucas定理,存在问题

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int p=1e9+7;
ll n,m;
ll quick_mod(ll a, ll b) {
	ll ans = 1;
	a %= p;
	while(b) {
		if(b & 1) {
			ans = ans * a % p;
			b--;
		}
		b >>= 1;
		a = a * a % p;
	}
	return ans;
}
ll C(ll n, ll m) {
	if(m > n) return 0;
	ll ans = 1;
	for(int i=1; i<=m; i++) {
		ll a = (n + i - m) % p;
		ll b = i % p;
		ans = ans * (a * quick_mod(b, p-2) % p) % p;
	}
	return ans;
}
ll Lucas(ll n, ll m) {
	if(m == 0) return 1;
	return C(n % p, m % p) * Lucas(n / p, m / p) % p;
}
int main() {
	scanf("%lld%lld", &n, &m);
	printf("%lld", Lucas(m+n,n)-Lucas(m+n,n+1));
	return 0;
}

ll b = i % p;
	ans = ans * (a * quick_mod(b, p-2) % p) % p;
}
return ans;

}
ll Lucas(ll n, ll m) {
if(m == 0) return 1;
return C(n % p, m % p) * Lucas(n / p, m / p) % p;
}
int main() {
scanf("%lld%lld", &n, &m);
printf("%lld", Lucas(m+n,n)-Lucas(m+n,n+1));
return 0;
}


逗比丶小酷 发布了3 篇原创文章 · 获赞 0 · 访问量 90 私信 关注

标签:Salle,Pui,La,int,ll,ans,x1,dp,r1
来源: https://blog.csdn.net/Frankie_Ku/article/details/104123518

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有