cf808 河南新手2 acwing周赛 北华

目录

cf808

牛客

北华


cf808

Dashboard - Codeforces Round #808 (Div. 2) - Codeforces

题意:能否将除了a1以外全变0,操作是a[i]更新成a[i]-a[i-1]

正解:从后往前考虑,每次都更新成a[1]
void solved()
{  
ll n;cin>>n;
for(int i=1;i<=n;i++)cin>>q[i];
 
    bool ok=1;
    for(int i=2;i<=n;i++)
    if(q[i]%q[1]==0)q[i]=q[1];
    else ok=0;
 
    puts(ok?"YES":"NO");
}

题意:给 [公式] ,构造一个长度为 [公式] 的数组,满足 [公式] 而且每一个 [公式] 互不相同。

正解:因为可以重复,所以直接从左边开始枚举
void solved()
{  
    ll n,l,r;cin>>n>>l>>r;
    bool ok=1;
    vector<ll> res;
    for(ll i=1;i<=n;i++)
    {
        ll x=l/i*i+(l%i==0?0:i);
        if(__gcd(x,i)==i&&x>=l&&x<=r)res.pb(x);
        else ok=0;
    }
    puts(ok?"YES":"NO");
    if(ok)
    {for(auto x:res)cout<<x<<' ';cout<<'\n';}
}

题意:尽可能多的打比赛,每次智商低于比赛难度,降智1

正解:贪心,最优最后一定降智为0

从后往前,mx智商够这场比赛一定1,否则再看mx和初始智商关系,mx小于初始智商也填1
signed main() {
    int T = read();
    while (T--) {
        int n;
        cin >> n;
        int q;
        cin>>q;
        minn=0;
        for(int i=1;i<=n;i++){
            a[i]=read();
            ans[i]=0;
        }
        for(int i=n;i>=1;i--){
            if(a[i]<=minn){
                ans[i]=1;
            }else if(minn<q){
                minn++;///靠自己
                ans[i]=1;
            }
        }
        for(int i=1;i<=n;i++){
            write(ans[i]);
        }
        puts("");
    }
}

牛客

这场周赛,我可以说是被揍得ma都不认识了,很多超时优化没写好,简单题被卡了也就没心态做其他的了,被卡一是锻炼临场分析问题能力,因此精神好的时候一定要多锻炼临场写题,但也不用天天练,一天最多正儿八经两场,二是平时没有积累,对此类问题得分析差

再回顾如果我能去开其他题,c模拟没问题,a如果是想到gcd可能有点困难,但是多码点条件可能可以过,签到是真笨b了,想到存d状态枚举abc,居然不知道存a+b枚举cd来优化,也是题目见少了把,好像竞赛书上有一个类似这样得枚举优化.。。

我艹,数论真是笨b,没猜到性质估计我赛时还是开不出来,tmlgjb有什么猜不猜得,就是从i枚举可能得答案日了艹

,G规律题,tmd打了表看数据,看不出来规律,斐波那契我还能看出来,这tm斐波那契+1就看不出来了,要我说还是题目见少了,其他得累了不想看,精神好了就去补

2022河南萌新联赛第(二)场:河南理工大学_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ (nowcoder.com)

找规律的题

用bfs模拟数据
容易知道a+b和奇偶性有关,再看9,18这个数据发现应该是和gcd==1有关
typedef pair<int,int> PII;
char g[45][45];
int a,b;
bool vis[45][45];
ll gcd(ll a,ll b)
{
    return b?gcd(a%b,a):a;
}
/*void bfs()
{
    queue<PII>q;
    q.push({1,1});
    int dx[]={a,a,-a,-a,b,b,-b,-b};
    int dy[]={b,-b,b,-b,a,-a,a,-a};
     
    while(q.size())
    {
        auto t=q.front();q.pop();
        for(int i=0;i<8;i++)
        {
            int xx=t.zx+dx[i],yy=t.zy+dy[i];
            if(xx<1||xx>20||yy<1||yy>20)continue;
            if(vis[xx][yy])continue;
            vis[xx][yy]=1;
            q.push({xx,yy});
        }
    }
}*/
void solved()
{  
    cin>>a>>b;
   /*bfs();
    for(int i=1;i<=20;i++)
    {
        for(int j=1;j<=20;j++)
            cout<<vis[i][j];cout<<'\n';
        }
    */
    puts((gcd(a,b)==1&&a!=b)?"Yes":"No");
}

最快考虑直接考虑最后一战勇者血条来判断就足够


模拟,02与 叫龙and boss对抗?

这些细节要清楚,下次很快可以码出来

进攻轮数上取整,勇士先手砍死就不用掉血 and 同余则不用吃临死一刀tt-(d.b/f.a==0||d.b%f.a==0)

然后叫龙全相同o1去算就可以,状态条件while+ ok d.cnt来划分,boos和叫龙伤害计算不同。。

此类可以直接考虑勇者能打死Boos,如果勇者血条<=0一定不能

struct node{
    int a,b,cnt=1;
}f,d,v;
int k;
void solved()
{  
    cin>>f.a>>f.b;
    cin>>d.a>>d.b>>d.cnt;
    cin>>k;
    cin>>v.a>>v.b;
     
    bool ok=0;
    ll ans=0;
    while(1)
    {
        if(ok)
        {
            if(d.cnt)
            {
                int tt=(d.b+f.a-1)/f.a;d.cnt=0;
                f.b-=(tt-(d.b/f.a==0||d.b%f.a==0))*(d.a)*k;
                f.b-=tt*v.a*k;
                ans+=tt*k;
                if(f.b<=0){puts("No Franxx!");return;}
            }
            else{
                int tt=(v.b+f.a-1)/f.a;
                f.b-=(tt-(v.b%f.a==0))*v.a;
                ans+=tt;
                if(f.b<=0){puts("No Franxx!");return;}
                else {cout<<ans<<'\n';return;}
            }
        }
        else{
            if(d.cnt==k){ok=1;continue;}
            int tt=(d.b+f.a-1)/f.a;ll cntt=d.cnt-k;d.cnt=k;
            ans+=tt*cntt;
            f.b-=(tt-(d.b/f.a==0||d.b%f.a==0))*d.a*cntt;
            if(f.b<=0){puts("No Franxx!");return;}
        }
    }
}

呆b艹
要求开三次根,范围很小枚举答案很快,约数得话能同余就是
void solved()
{  
    cin>>n;cnt=0;
     for (ll i = 1; i*i*i<=n; i ++ )
        if(n%(i*i*i)==0)cnt++;
    cout<<cnt<<'\n';
}

至少学会了set模拟集合

看不出来规律,笑死,码完出个规律总结

类似斐波那契但多+1
void solved()
{  
    /*
    set<int>s;s.insert(1);
    int ss[9999]={0};
     
    int sum=0;
    for(auto& x:s)
    {
        if(x>=9999)break;
        ss[x]=1;
        s.insert(4*x),s.insert(2*x+1);
    }
    for(int i=1;i<=9999;i++)ss[i]+=ss[i-1];
     
    for(int i=2;i<=9999;i*=2)
        cout<<ss[i]<<' ';cout<<'\n';
    */
    q[1]=1,q[2]=2;
    for(int i=3;i<=1000000;i++)
        q[i]=(q[i-1]+q[i-2]+1)%p;
     
    int x;cin>>x;cout<<q[x]<<'\n';
 
}

t🐎了,枚举无序pair 理论时间复杂度1e7完全够,被卡常数

正解:分成两端on^2存a+b的状态

再枚举d-c是否等于a
时间复杂度就on方
1e3下 a+b+c+d=常已经极限了吧
map代替二分搜索

unordered_map<ll,ll>mp;
void solved()
{  
ll n;cin>>n;
 
    ll mx=0;
    for(ll i=1;i<=n;i++)cin>>q[i];
     
        if(n==1){puts("No");return;}
     
    for(int i=1;i<=n;i++)
        for(int j=i;j<=n;j++)
            if(!mp[q[i]+q[j]])mp[q[i]+q[j]]++;
 
        for(int i=n;i>=1;i--)
        {
            for(int j=1;j<=n;j++)
            {
                    ll ans=q[i]-q[j];
                    if(mp[ans]){cout<<"Yes"<<'\n';return;}
            }
        }
    cout<<"No"<<'\n';
}

开门wa逆天签到题不跑完i算我运行错误,服了,以后不考虑了,反正substr可以空
void solved()
{  
    ll res=0;
    string ss="HPU";
string s;cin>>s;
     
    for(int i=0;i<s.size();i++)
    {
        if(s.substr(i,3)==ss)res++;
    }
    cout<<res<<'\n';
}

和前一个枚举和一样的思路,但是注意除数的细节
然后牛客有的哈希才能过,cf就必须map。。。
const int N = 1510;
 
LL n;
LL q[N];
unordered_map<int,int>mp;
void solved()
{  
cin>>n;
    for(int i=1;i<=n;i++)cin>>q[i];
     
    for(int i=2;i<=n;i++)
        for(int j=i;j<=n;j++)
            mp[q[i]*q[j]]=i;
     
    LL cnt=0;
    for(int i=1;i<n;i++)
        for(int j=i+1;j<=n;j++)
        {
            if(!q[i]&&!q[j]){cnt++;break;}
            else if(!q[j]||q[i]%q[j])continue;
            else if(mp[q[i]/q[j]]>i){cnt++;break;}
        }
     
    cout<<cnt<<'\n';
}

//很多细节还是没有非常清楚,但维护状态是这个个板子》。


化简题意:求s[r]-x<=s[l-1]的个数

离散化+树状数组维护

离散化操作是将q[i]映射到vector的下标
再用缩小的下标来维护树状数组长度

const int N = 2e5 + 10;
LL n,x,y;
LL q[N];
int tr[N];
vector<LL>res;
LL find(LL x)
{
    return lower_bound(res.begin(),res.end(),x)-res.begin()+1;
}
void add(LL x,LL w)
{
    for(int i=x;i<=res.size();i+=lowbit(i))
        tr[i]+=w;
}
LL query(LL x)
{
    LL ans=0;
    for(int i=x;i>=1;i-=lowbit(i))
        ans+=tr[i];
    return ans;
}
void solved()
{  
    cin>>n>>x>>y;
    for(int i=1;i<=n;i++)cin>>q[i],q[i]-=y,q[i]+=q[i-1],res.pb(q[i]);
    每次add的是s[l-1],所以要add 0
    res.pb(0);
    
    sort(res.begin(),res.end());
    res.erase((res.begin(),res.end()),res.end());
    
    add(find(0),1);
    LL ans=0;
    for(int i=1;i<=n;i++)
    {
求大于等于s[r]-x的个数,-1应该是离散化从1开始的原因?
        ans+=i-query(find(q[i]-x)-1);
        add(find(q[i]),1);
    }
    cout<<ans<<'\n';
}

计算几何偷jiao老师的板子嘻嘻

#include <bits/stdc++.h>

#define y1 qwq

using namespace std;

const double inf=1e20;
const double eps=1e-8;
const double pi=acos(-1.0);
const int maxp=1010;

//判断正负
int sgn(double x) {
	if (fabs(x)<eps) return 0;
	if (x<0) return -1;
	else return 1;
}
//平方
inline double sqr(double x) {
	return x*x;
}

struct Point {
	double x,y;
	Point() {}
	Point(double _x, double _y) {
		x=_x;
		y=_y;
	}
	void input() {
		scanf("%lf%lf",&x,&y);
	}
	void output() {
		printf("%.2f%.2f\n",x,y);
	}
	bool operator == (Point b)const {
		return sgn(x-b.x)==0 && sgn(y-b.y)==0;
	}
	bool operator < (Point b)const {
		return sgn(x-b.x)==0?sgn(y-b.y)<0:x<b.x;
	}
	Point operator -(const Point &b)const {
		return Point(x-b.x,y-b.y);
	}
	//叉积
	double operator ^(const Point &b)const {
		return x*b.y-y*b.x;
	}
	//点积
	double operator *(const Point &b)const {
		return x*b.x+y*b.y;
	}
	//返回长度
	double len() {
		return hypot(x,y);
	}
	//返回长度平方
	double len2() {
		return x*x+y*y;
	}
	//返回两点间距
	double distance(Point p) {
		return hypot(x-p.x,y-p.y);
	}
	Point operator +(const Point &b)const {
		return Point(x+b.x,y+b.y);
	}
	Point operator *(const double &k)const {
		return Point(x*k,y*k);
	}
	Point operator /(const double &k)const {
		return Point(x/k,y/k);
	}
	//pa和pb的夹角
	double rad(Point a,Point b) {
		Point p=*this;
		return fabs(atan2(fabs((a-p)^(b-p)),(a-p)*(b-p)));
	}
	//化为长度为r的向量
	Point trunc(double r) {
		double l=len();
		if (!sgn(l)) return *this;
		r/=l;
		return Point(x*r,y*r);
	}
	//逆时针旋转 90 度
	Point rotleft() {
		return Point(-y,x);
	}
	//顺时针旋转 90 度
	Point rotright() {
		return Point(y,-x);
	}
	//绕着 p 点逆时针旋转 angle
	Point rotate(Point p,double angle) {
		Point v=(*this)-p;
		double c=cos(angle),s=sin(angle);
		return Point(p.x+v.x*c-v.y*s,p.y+v.x*s+v.y*c);
	}
};

struct Line {
	Point s,e;
	Line() {}
	Line(Point _s,Point _e) {
		s=_s;
		e=_e;
	}
	bool operator ==(Line v) {
		return (s==v.s) && (e==v.e);
	}
	//根据一个点和倾斜角 angle 确定直线,0<=angle<π
	Line(Point p, double angle) {
		s=p;
		if (sgn(angle-pi/2)==0) {
			e=(s+Point(0,1));
		} 
		else {
			e=(s+Point(1,tan(angle)));
		}
	}
	//ax+by+c=0
	Line(double a,double b,double c) {
		if(sgn(a)==0) {
			s=Point(0,-c/b);
			e=Point(1,-c/b);
		} 
		else if(sgn(b)==0) {
			s=Point(-c/a,0);
			e=Point(-c/a,1);
		} 
		else {
			s=Point(0,-c/b);
			e=Point(1,(-c-a)/b);
		}
	}
	void input() {
		s.input();
		e.input();
	}
	void adjust() {
		if(e<s) swap(s,e);	
	}
	//求线段长度
	double length() {
		return s.distance(e);
	}
	//返回直线倾斜角 0<=angle<π 
	double angle() {
		double k=atan2(e.y-s.y,e.x-s.x);
		if(sgn(k)<0) k+=pi;
		if(sgn(k-pi)==0) k-= pi;
		return k;
	}
	//点和直线关系
	// 1 在左侧
	// 2 在右侧
	// 3 在直线上 
	int relation(Point p) {
		int c=sgn((p-s)^(e-s));
		if(c<0) return 1; 
		else if(c>0) return 2; 
		else return 3;	 
	}
	//点在线段上的判断
	bool pointonseg(Point p) {
		return sgn((p-s)^(e-s))==0 && sgn((p-s)*(p-e))<=0;
	}
	//两向量平行 (对应直线平行或重合)
	bool parallel(Line v) {
		return sgn((e-s)^(v.e-v.s))==0;
	}
	//两线段相交判断
	//2 规范相交
	//1 非规范相交
	//0 不相交
	int segcrossseg(Line v) {
		int d1=sgn((e-s)^(v.s-s));
		int d2=sgn((e-s)^(v.e-s));
		int d3=sgn((v.e-v.s)^(s-v.s));
		int d4=sgn((v.e-v.s)^(e-v.s));
		if((d1^d2)==-2&&(d3^d4)==-2)return 2;
		return (d1==0 && sgn((v.s-s)*(v.s-e))<=0) ||
		       (d2==0 && sgn((v.e-s)*(v.e-e))<=0) ||
		       (d3==0 && sgn((s-v.s)*(s-v.e))<=0) ||
		       (d4==0 && sgn((e-v.s)*(e-v.e))<=0);
	}
	//直线和线段相交判断
	//-*this line -v seg
	//2 规范相交
	//1 非规范相交
	//0 不相交
	int linecrossseg(Line v) {
		int d1=sgn((e-s)^(v.s-s));
		int d2=sgn((e-s)^(v.e-s));
		if((d1^d2)==-2) return 2;
		return (d1==0||d2==0);
	}
	//两直线关系
	//0 平行
	//1 重合
	//2 相交
	int linecrossline(Line v) {
		if((*this).parallel(v))
			return v.relation(s)==3;
		return 2;
	}
	//求两直线的交点
	//要保证两直线不平行或重合
	Point crosspoint(Line v) {
		double a1 = (v.e-v.s)^(s-v.s);
		double a2 = (v.e-v.s)^(e-v.s);
		return Point((s.x*a2-e.x*a1)/(a2-a1),(s.y*a2-e.y*a1)/(a2-a1
		                                                     ));
	}
	//点到直线的距离
	double dispointtoline(Point p) {
		return fabs((p-s)^(e-s))/length();
	}
	//点到线段的距离
	double dispointtoseg(Point p) {
		if(sgn((p-s)*(e-s))<0 || sgn((p-e)*(s-e))<0)
			return min(p.distance(s),p.distance(e));
		return dispointtoline(p);
	}
	//返回线段到线段的距离
	//前提是两线段不相交,相交距离就是 0 了
	double dissegtoseg(Line v) {
		return min(min(dispointtoseg(v.s),dispointtoseg(v.e)),min(v
		           .dispointtoseg(s),v.dispointtoseg(e)));
	}
	//返回点 p 在直线上的投影
	Point lineprog(Point p) {
		return s + ( ((e-s)*((e-s)*(p-s)))/((e-s).len2()) );
	}
	//返回点 p 关于直线的对称点
	Point symmetrypoint(Point p) {
		Point q = lineprog(p);
		return Point(2*q.x-p.x,2*q.y-p.y);
	}
};

struct circle {
	Point p; //圆心
	double r; //半径
	circle() {}
	circle(Point _p,double _r) {
		p=_p;
		r=_r;
	}
	circle(double x,double y,double _r) {
		p=Point(x,y);
		r=_r;
	}
	//三角形的外接圆
	//需要 Point 的 + / rotate() 以及 Line 的 crosspoint()
	//利用两条边的中垂线得到圆心
	circle(Point a,Point b,Point c) {
		Line u=Line((a+b)/2,((a+b)/2)+((b-a).rotleft()));
		Line v=Line((b+c)/2,((b+c)/2)+((c-b).rotleft()));
		p=u.crosspoint(v);
		r=p.distance(a);
	}
	//三角形的内切圆
	//参数 bool t 没有作用,只是为了和上面外接圆函数区别
	circle(Point a,Point b,Point c,bool t) {
		Line u,v;
		double m=atan2(b.y-a.y,b.x-a.x),n=atan2(c.y-a.y,c.x-a.x);
		u.s=a;
		u.e=u.s+Point(cos((n+m)/2),sin((n+m)/2));
		v.s=b;
		m=atan2(a.y-b.y,a.x-b.x),n=atan2(c.y-b.y,c.x-b.x);
		v.e=v.s+Point(cos((n+m)/2),sin((n+m)/2));
		p=u.crosspoint(v);
		r=Line(a,b).dispointtoseg(p);
	}
	void input() {
		p.input();
		scanf("%lf",&r);
	}
	void output() {
		printf("%.2lf-%.2lf-%.2lf\n",p.x,p.y,r);
	}
	bool operator == (circle v) {
		return (p==v.p) && sgn(r-v.r)==0;
	}
	bool operator < (circle v)const {
		return ((p<v.p) || ((p==v.p) && sgn(r-v.r)<0));
	}
	//面积
	double area() {
		return pi*r*r;
	}
	//周长
	double circumference() {
		return 2*pi*r;
	}
	//点和圆的关系
	//0 圆外
	//1 圆上
	//2 圆内
	int relation(Point b) {
		double dst=b.distance(p);
		if (sgn(dst-r)<0) return 2;
		else if (sgn(dst-r)==0) return 1;
		return 0;
	}
	//线段和圆的关系
	//比较的是圆心到线段的距离和半径的关系
	int relationseg(Line v) {
		double dst=v.dispointtoseg(p);
		if (sgn(dst-r)<0) return 2;
		else if (sgn(dst-r)==0) return 1;
		return 0;
	}
	//直线和圆的关系
	//比较的是圆心到直线的距离和半径的关系
	int relationline(Line v) {
		double dst=v.dispointtoline(p);
		if (sgn(dst-r)<0) return 2;
		else if (sgn(dst-r)==0) return 1;
		return 0;
	}
	//两圆的关系
	//5 相离
	//4 外切
	//3 相交
	//2 内切
	//1 内含
	//需要 Point 的 distance
	int relationcircle(circle v) {
		double d=p.distance(v.p);
		if (sgn(d-r-v.r)>0) return 5;
		if (sgn(d-r-v.r)==0) return 4;
		double l=fabs(r-v.r);
		if (sgn(d-r-v.r)<0 && sgn(d-l)>0) return 3;
		if (sgn(d-l)==0) return 2;
		if (sgn(d-l)<0) return 1;
        return 0;
	}
	//求两个圆的交点,返回 0 表示没有交点,返回 1 是一个交点,2 是两个交点
	//需要 relationcircle
	int pointcrosscircle(circle v,Point &p1,Point &p2) {
		int rel=relationcircle(v);
		if (rel==1 || rel==5)return 0;
		double d=p.distance(v.p);
		double l=(d*d+r*r-v.r*v.r)/(2*d);
		double h=sqrt(r*r-l*l);
		Point tmp=p+(v.p-p).trunc(l);
		p1=tmp+((v.p-p).rotleft().trunc(h));
		p2=tmp+((v.p-p).rotright().trunc(h));
		if(rel==2 || rel==4)
			return 1;
		return 2;
	}
	//求直线和圆的交点,返回交点个数
	int pointcrossline(Line v,Point &p1,Point &p2) {
		if (!(*this).relationline(v)) return 0;
		Point a=v.lineprog(p);
		double d=v.dispointtoline(p);
		d=sqrt(r*r-d*d);
		if (sgn(d)==0) {
			p1=a;
			p2=a;
			return 1;
		}
		p1=a+(v.e-v.s).trunc(d);
		p2=a-(v.e-v.s).trunc(d);
		return 2;
	}
	//得到过 a,b 两点,半径为 r1 的两个圆
	int gercircle(Point a,Point b,double r1,circle &c1,circle &c2) {
		circle x(a,r1),y(b,r1);
		int t=x.pointcrosscircle(y,c1.p,c2.p);
		if (!t) return 0;
		c1.r=c2.r=r;
		return t;
	}
	//得到与直线 u 相切,过点 q, 半径为 r1 的圆
	int getcircle(Line u,Point q,double r1,circle &c1,circle &c2) {
		double dis = u.dispointtoline(q);
		if (sgn(dis-r1*2)>0) return 0;
		if (sgn(dis)==0) {
			c1.p=q+((u.e-u.s).rotleft().trunc(r1));
			c2.p=q+((u.e-u.s).rotright().trunc(r1));
			c1.r=c2.r=r1;
			return 2;
		}

		Line u1=Line((u.s+(u.e-u.s).rotleft().trunc(r1)),(u.e+(u.e-u.s).rotleft().trunc(r1)));
		Line u2=Line((u.s + (u.e-u.s).rotright().trunc(r1)),(u.e+(u.e-u.s).rotright().trunc(r1)));
		circle cc=circle(q,r1);
		Point p1,p2;
		if (!cc.pointcrossline(u1,p1,p2))
			cc.pointcrossline(u2,p1,p2);
		c1=circle(p1,r1);
		if (p1==p2) {
			c2=c1;
			return 1;
		}
		c2=circle(p2,r1);
		return 2;
	}
	//同时与直线 u,v 相切,半径为 r1 的圆
	int getcircle (Line u,Line v,double r1,circle &c1,circle &c2,circle &c3,circle &c4) {
		if(u.parallel(v))return 0;//两直线平行
		Line u1=Line(u.s+(u.e-u.s).rotleft().trunc(r1),u.e+(u.e-u.s).rotleft().trunc(r1));
		Line u2=Line(u.s+(u.e-u.s).rotright().trunc(r1),u.e+(u.e-u.s).rotright().trunc(r1));
		Line v1=Line(v.s+(v.e-v.s).rotleft().trunc(r1),v.e+(v.e-v.s).rotleft().trunc(r1));
		Line v2=Line(v.s+(v.e-v.s).rotright().trunc(r1),v.e+(v.e-v.s).rotright().trunc(r1));
		c1.r=c2.r=c3.r=c4.r=r1;
		c1.p=u1.crosspoint(v1);
		c2.p=u1.crosspoint(v2);
		c3.p=u2.crosspoint(v1);
		c4.p=u2.crosspoint(v2);
		return 4;
	}
	//同时与不相交圆 cx,cy 相切,半径为 r1 的圆
	int getcircle(circle cx,circle cy,double r1,circle &c1,circle &c2) {
		circle x(cx.p,r1+cx.r),y(cy.p,r1+cy.r);
		int t=x.pointcrosscircle(y,c1.p,c2.p);
		if (!t) return 0;
		c1.r=c2.r=r1;
		return t;
	}

	//过一点作圆的切线 (先判断点和圆的关系)
	int tangentline(Point q,Line &u,Line &v) {
		int x=relation(q);
		if (x==2) return 0;
		if (x==1) {
			u=Line(q,q+(q-p).rotleft());
			v=u;
			return 1;
		}
		double d=p.distance(q);
		double l=r*r/d;
		double h=sqrt(r*r-l*l);
		u=Line(q,p+((q-p).trunc(l)+(q-p).rotleft().trunc(h)));
		v=Line(q,p+((q-p).trunc(l)+(q-p).rotright().trunc(h)));
		return 2;
	}
	//求两圆相交的面积
	double areacircle(circle v) {
		int rel=relationcircle(v);
		if (rel>=4) return 0.0;
		if (rel<=2) return min(area(),v.area());
		double d=p.distance(v.p);
		double hf=(r+v.r+d)/2.0;
		double ss=2*sqrt(hf*(hf-r)*(hf-v.r)*(hf-d));
		double a1=acos((r*r+d*d-v.r*v.r)/(2.0*r*d));
		a1=a1*r*r;
		double a2=acos((v.r*v.r+d*d-r*r)/(2.0*v.r*d));
		a2=a2*v.r*v.r;
		return a1+a2-ss;
	}
	//求圆和三角形 pab 的相交面积
	double areatriangle(Point a,Point b) {
		if (sgn((p-a)^(p-b))==0) return 0.0;
		Point q[5];
		int len=0;
		q[len++]=a;
		Line l(a,b);
		Point p1,p2;
		if (pointcrossline(l,q[1],q[2])==2) {
			if (sgn((a-q[1])*(b-q[1]))<0) q[len++]=q[1];
			if (sgn((a-q[2])*(b-q[2]))<0) q[len++]=q[2];
		}
		q[len++]=b;
		if (len==4 && sgn((q[0]-q[1])*(q[2]-q[1]))>0) swap(q[1],q[2]);
		double res=0;
		for (int i=0; i<len-1; i++) {
			if (relation(q[i])==0||relation(q[i+1])==0) {
				double arg=p.rad(q[i],q[i+1]);
				res+=r*r*arg/2.0;
			} 
			else {
				res+=fabs((q[i]-p)^(q[i+1]-p))/2.0;
			}
		}
		return res;
	}
};

double x1, y1, r1;
double x2, y2, r2;

int main() {
    cin >> x1 >> y1 >> r1 >> x2 >> y2 >> r2;
    circle a = {x1, y1, r1}, b = {x2, y2, r2};
    Point O = {0, 0};
    Line p, q, r, s;
    a.tangentline(O, p, q), b.tangentline(O, r, s);
    bool ok = true;
    if (a.relationseg(r) && a.relationseg(s)) ok = false;
    if (b.relationseg(p) && b.relationseg(q)) ok = false;
    puts(ok ? "Yes" : "No");
    return 0;
}
题意:求数位*2==各数位和

因为数位最多为10,数位和最多20所以dfs加上剪肢就很快了

dfs存下各位状态,在循环中dfs

LL n;
LL ans=0;
void dfs(LL x,int sum,int dgit)
{
    if(x>n||dgit>10||sum>20)return;
    if(x&&dgit*2==sum)ans++;
     
    for(int i=0;i<=9;i++)
    {
        LL y=x*10+i;
        if(y&&y<=n)dfs(y,sum+i,dgit+1);
    }
}
void solved()
{  
    cin>>n;
    dfs(0,0,0);
    cout<<ans<<'\n';
}

线段树维护奇数,偶数时的状态

区间修改+懒标记,查询总和即根节点

struct node {
     
    int l , r;
    LL o, e;
    bool tag;
} tr[N << 2];
int n, m;
int w[N];
 
void pushup(int u)
{
    tr[u].o = tr[u << 1].o + tr[u << 1 | 1].o;
    tr[u].e = tr[u << 1].e + tr[u << 1 | 1].e;
}
 
void pushtag(int u)
{
    LL tmp = tr[u].e;
    tr[u].e = tr[u].o<<1;
    tr[u].o = tmp>>1;
    tr[u].tag ^= 1;
}
 
void pushdown(int u)
{
    if(tr[u].tag) {
        pushtag(u << 1);
        pushtag(u << 1 | 1);
        tr[u].tag = 0;
    }
}
void build(int u, int l, int r)
{
    tr[u] = {l, r};
    if(l == r)tr[u].o = w[l];
    else{
        int mid=l + r >> 1;
        build(u << 1, l, mid);
        build(u << 1 | 1, mid + 1, r);
        pushup(u);
    }   
}
 
void modify(int u, int l, int r)
{
    if(tr[u].l >= l && tr[u].r <= r)
        return pushtag(u);
    int mid = tr[u].l + tr[u].r >> 1;
    pushdown(u);
    if(l <= mid) modify(u << 1, l , r);
    if(r > mid) modify(u << 1 | 1, l ,r);
    pushup(u);
}
void solved()
{  
    cin>>n>>m;
    for(int i=1;i<=n;i++)cin>>w[i];
    build(1,1,n);
    while(m--)
    {
        int l, r;cin >> l >> r;
        modify(1, l, r);
        cout << tr[1].o+tr[1].e << '\n';
    }
}

北华大学计算机程序设计算法提高训练营个人赛_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ (nowcoder.com)

bfs求最短路
最呆可以on^2预处理,不知道为什么每层来匹配求答案不能过全部数据

碰到这种情况多换几种写法吧,周赛也是,能过样例和大部分数据说明整体思路没问题,有些东西考虑不到,换下写法可能就过了。。。这里换的写法是存每次点的距离从上一个点来,直接return

想On过,考虑,直接把同性的点加入队列,存性别,距离初始化成0,若目标v是异性点才更新距离
存一个二维,g[i][1]:第i个点,这个1的意思是雌性能被到的距离


int n,m,tt;
int g[N][2];
bool sex[N];
vector<int>G[N];
void bfs(int f)
{
    queue<int> q;
    for(int i=1;i<=n;i++)
    if(sex[i]==f)q.push(i),g[i][f]=0;
    while (!q.empty())
    {
        auto t = q.front();q.pop();
        for (auto v : G[t])
        {
            if(g[v][f]==-1&&sex[v]!=f)
            {
                g[v][f]=g[t][f]+1;
                q.push(v);
            }
        }
    }
}
 
void solved()
{  
    cin>>n>>m>>tt;
    for(int i=1;i<=n;i++)cin>>sex[i];
    while(m--)
    {
        int u,v;cin>>u>>v;
        G[u].pb(v),G[v].pb(u);
    }
    memset(g,-1,sizeof g);
    bfs(0);
    bfs(1);
    int x;
    while(tt--)
    {
        cin>>x;
        if(sex[x])cout<<g[x][0]<<'\n';
        else cout<<g[x][1]<<'\n';
    }
}

北华

鸡兔同笼,直接二元一次方程就出来了,不知道以前为啥只会先假设腿少的,求腿多的..

LL x,y,H,F;
void solved()
{  
    LL a,b;
    cin>>x>>y>>H>>F;
    bool ok=1;
    if(x>y)swap(x,y),ok=0;
     
    b=(F-H*x)/(y-x);
    a=H-b;
     
    if(ok)cout<<a<<' '<<b<<'\n';
    else cout<<b<<' '<<a<<'\n';
}

贪心使经验溢出最少

尽量把高经验的书用到差一步溢出,其余同理(每一步看经验书经验能否大于当前res,有多的才会有取Min)
再从最小经验书用,不够就换大的

还可能直接用高经验书会更优,所以和溢出时取min

LL x,y,a,b,c;
void solved()
{  
    cin>>x>>y>>a>>b>>c;
    LL res=(2000+(x-1)*y-y)*(x-1)/2;
    LL ans=a*20000+b*5000+c*1000;
    
     if(ans<res){puts("QAQ");return;}
    
    ans=1e18;
    if(a*20000>=res)
    {
     a-=res/20000;
    res%=20000;
        if(a>0)ans=min(ans,20000-res);
    }
    else{
        res-=a*20000;
        a=0;
    }
    
    if(b*5000>=res)
    {
     b-=res/5000;
    res%=5000;
        if(b>0)ans=min(ans,5000-res);
    }
    else{
        res-=b*5000;
        b=0;
    }
     
    if(c*1000>=res)
    {
     c-=res/1000;
    res%=1000;
        if(c>0)ans=min(ans,1000-res);
    }
    else{
        res-=c*1000;
        c=0;
    }
    
    if(res==0)cout<<res<<'\n';
    else if(c!=0)cout<<min(ans,1000-res)<<'\n';
    else if(b!=0)cout<<min(ans,5000-res)<<'\n';
    else if(a!=0)cout<<min(ans,20000-res)<<'\n';
}

bfs终点,终点能到的地方就是合理的

struct node
{
    int x,y;
}ed,w[1000010];
 
int dx[]={0,0,-1,1};
int dy[]={1,-1,0,0};
void bfs(int x,int y)
{
    queue<PII>q;
    q.push({x,y});
    vis[x][y]=1;
     
    while(!q.empty())
    {
        auto t=q.front();q.pop();
        for(int i=0;i<4;i++)
        {
            int xx=t.zx+dx[i],yy=t.zy+dy[i];
            if(xx<1||xx>n||yy<1||yy>m)continue;
            if(vis[xx][yy]||g[xx][yy]=='#')continue;
            vis[xx][yy]=1;
            q.push({xx,yy});
        }
    }
}
 
void solved()
{  
    cin>>n>>m>>tt;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            cin>>g[i][j];
    for(int i=1;i<=tt;i++)cin>>w[i].x>>w[i].y;
    cin>>ed.x>>ed.y;
    //cout<<ed.x<<ed.y;
    bfs(ed.x,ed.y);
    int cnt=0;
    vector<int>res;
    for(int i=1;i<=tt;i++)
        if(vis[w[i].x][w[i].y])cnt++,res.pb(i);
   
    cout<<cnt<<'\n';
    for(auto x:res)
        cout<<x<<' ';cout<<'\n';
}

nim博弈变形:每次没堆都要取

结论:最多能取x,则数量为x+1倍数必输

此题是空了就算输,上着应该是全部取空得结论,所以更新输赢最快得轮数

LL a,b,c;
LL w,l;
void solved()
{  
		cin>>a>>b>>c;
    w=l=2e9;
    
    if(a%4)w=min(w,a/4);
    else l=min(l,a/4);
    
    if(b%5)w=min(w,b/5);
    else l=min(l,b/5);
    
    if(c%6)w=min(w,c/6);
    else l=min(l,c/6);
    
    if(w<l)cout<<"(^-^)"<<'\n';
    else cout<<"(T-T)"<<'\n';
}

a[i]+a[j]==m且i<j

统计对数,想直接存a[i]状态, 做减法查找下标过不了全部数据...


这里二元,排序后,遍历到+上存过的状态能行,挺经典了这种题目

LL n,m;
LL q[N];
map<LL,LL>mp;
void solved()
{  
    cin>>n>>m;
    for(int i=1;i<=n;i++)cin>>q[i];
    sort(q+1,q+n+1);
    LL cnt=0;
    for(int i=1;i<=n;i++)
    {
        if(q[i]>m)break;
        cnt+=mp[m-q[i]];
        mp[q[i]]++;
    }
     
    cout<<cnt<<'\n';
}

模拟题能看懂样例的意思是3*3的矩阵,o1查找


LL g[5][5];
LL n,t;
string s;
map<string,int> mp;
void solved()
{  
    mp["First Class"]=1;
    mp["Business Class"]=2;
    mp["Economy Class"]=3;
   cin>>n>>t;
    getline(cin,s);
    getline(cin,s);
 
    for(int i=1;i<=3;i++)
        for(int j=1;j<=3;j++)
            cin>>g[i][j];
    LL line=mp[s],col=0;
    if(t>=336)col=0;
    else if(t>=48)col=1;
    else if(t>=4)col=2;
    else col=3;
   // cout<<line<<col;
    printf("%.2lf",(1-g[line][col]*1.0/100)*n);
     
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值