目录
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);
}