CF解题报告:2

T1 Winner

题目

注意 题目中如果两名或两名以上的玩家在比赛结束时都有最大的分数 m m m,那么其中首先获得至少 m m m分的玩家胜利。
至少 m m m

#include<bits/stdc++.h>
using namespace std;
typedef double db;
typedef long long ll;
const int N=1007;
int n,x[N];
string s[N],ans;
map<string,int> mp,vis,m;
int main(){
    scanf("%d",&n);
    int MAX=-1e9;
    for(int i=1;i<=n;i++){
        cin>>s[i]>>x[i];
        mp[s[i]]+=x[i];
    }
    for(int i=1;i<=n;i++) MAX=max(MAX,mp[s[i]]);
    for(int i=1;i<=n;i++){
        m[s[i]]+=x[i];
        if(m[s[i]]>=MAX && mp[s[i]]==MAX) {
        	ans=s[i];
        	break;
		}
    }
    cout<<ans<<'\n';
}

T2 The least round way

题目

注意到 若一个数有 n n n个0结尾,那么它的分解质因子就有 n n n ( 2 , 5 ) (2,5) 25 的因子
比如:
120 = 2 ∗ 2 ∗ 5 ∗ 6 120=2*2*5*6 120=2256,有1对 ( 2 , 5 ) (2,5) 25 故有1个0结尾
600 = 2 ∗ 2 ∗ 5 ∗ 5 ∗ 6 600=2*2*5*5*6 600=22556,有2对 ( 2 , 5 ) (2,5) 25 故有2个0结尾
对2与5分别DP,取最小
若路径有0,那最多有1个0结尾,注意特判

#include<bits/stdc++.h> 
using namespace std;
const int Inf=0x7FFFFFFF,N=1007;
int n,t,num[N][N][2],f[N][N][2];
void Print(int i,int j,int k) {
    if(i==1&&j==1) {             
        putchar(k? 'D':'R');
        return ;           
    }
    if(i==1)
        Print(i,j-1,0);
    else if(j==1)
        Print(i-1,j,1);
    else if(f[i][j][t]==f[i][j-1][t]+num[i][j][t])
        Print(i,j-1,0);
    else
        Print(i-1,j,1);
    if(i!=n||j!=n)
        putchar(k? 'D':'R');   
}
int main() {
    int ans;
    scanf("%d",&n);
    for(int i=1,k;i<=n;++i)
        for(int j=1;j<=n;++j) {  
            scanf("%d",&k);
            if(!k) {
                num[i][j][0]=num[i][j][1]=1;
                t=i;    
            }
            else {
                for(;!(k%2);k/=2)
                    ++num[i][j][0];
                for(;!(k%5);k/=5)
                    ++num[i][j][1];
            }
        }
    for(int i=1;i<=n;++i)
        f[0][i][0]=f[i][0][0]=f[0][i][1]=f[i][0][1]=Inf;    
    f[1][1][0]=num[1][1][0];
    f[1][1][1]=num[1][1][1];
    for(int k=0;k<2;++k)
        for(int i=1;i<=n;++i)
            for(int j=i==1? 2:1;j<=n;++j)
                f[i][j][k]=min(f[i][j-1][k],f[i-1][j][k])+num[i][j][k];
    ans=min(f[n][n][0],f[n][n][1]);
    if(t&&ans>1) {           
        printf("1\n");
        for(int i=1;i<t;++i)
            putchar('D');
        for(int i=1;i<n;++i)
            putchar('R');
        for(int i=t;i<n;++i)
            putchar('D');
    }
    else {                 
        printf("%d\n",ans);
        t=!(f[n][n][0]<f[n][n][1]);
        Print(n,n,0);
    }
}

T3 Commentator problem

题目

一个点到一个圆的切线角度可以用距离/半径表示。
解一下二元二次方程就可以了。

#include<bits/stdc++.h>
using namespace std;
typedef double db;
const db eps=1e-7;
int cmp(const db &x){ return x<-eps?-1:x>eps;}
struct circle{
	db x,y,r;
	void re(){
		cin>>x>>y>>r;
	}
};
circle C1,C2,C3;
db pow(const db &x){ return x*x; }
void get(circle C1,circle C2,db &a,db &bx,db &by,db &c){//求出形如 (a*(x^2))+(a*(y^2))+(bx*x)+(by*y)+c=0的二元二次方程的所有系数
	db k;
#define add(r,x,y,w) k=pow(r)*w;a+=k;bx-=k*2*x;by-=k*2*y;c+=k*(pow(x)+pow(y)); 
	add(C2.r,C1.x,C1.y,1)
	add(C1.r,C2.x,C2.y,-1)
#undef add
}
void work(db a,db b,db c,db &x1,db &x2){
	if(!cmp(a)){
		x1=x2=-c/b;
		return ;
	}
	if(cmp(pow(b)-4*a*c)<0)exit(0); 
	db s=-b/(2*a),d=sqrt(pow(b)-4*a*c)/(2*a);
	x1=s+d;x2=s-d;
}
db dis1(db x,db y){ return pow(x-C1.x)+pow(y-C1.y); }
int main(){
	C1.re();C2.re();C3.re();
	db a1=0,a2=0,bx1=0,by1=0,c1=0,bx2=0,by2=0,c2=0;
	get(C1,C2,a1,bx1,by1,c1);
	get(C1,C3,a2,bx2,by2,c2);
	db a=a2*bx1-a1*bx2,b=a2*by1-a1*by2,c=a2*c1-a1*c2;
	if(!cmp(a1)){
		if(!cmp(a2)){
			#define work(x1,y1,x2,y2) -(c1*y2-c2*y1)/(x1*y2-x2*y1) 
				printf("%.5lf %.5lf\n",work(bx1,by1,bx2,by2),work(by1,bx1,by2,bx2));
			#undef work
			return 0;
		}
		a=bx1;b=by1;c=c1;
		swap(a1,a2);swap(bx1,bx2);swap(by1,by2);swap(c1,c2);	
	}
	bool check=0;
	if(!cmp(b)){check=1;swap(a,b);swap(bx1,by1);}
	a=-a/b;c=-c/b;
	db x1,x2;
	work( a1*(1+pow(a)),bx1+a1*2*a*c+by1*a,a1*pow(c)+by1*c+c1 ,x1,x2);
	db y1=a*x1+c,y2=a*x2+c; 
	if(check){swap(x1,y1);swap(x2,y2);}
	if(dis1(x1,y1)>dis1(x2,y2)){swap(x1,x2);swap(y1,y2);}
	printf("%.5lf %.5lf\n",x1,y1);
}

积累

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值