挺好玩的一场比赛。
A
打表,打到\(2e4\)左右会发现有一个长度\(104\)的循环节。
#include<bits/stdc++.h>
using namespace std;
int col[5010][5010];
int dx[4] = {1,0,-1,0},dy[4] = {0,1,0,-1};
long long n,tem=0;
int main()
{
cin >> n;
int x=0,y=0,d=0;
while(tem<n){
++tem;
x = x+dx[d], y = y+dy[d];
if(!col[x+2500][y+2500])d++;
else d--;
d+=4;d%=4;
col[x+2500][y+2500]^=1;
if(tem>=15447 && (n-tem)%104==0){
long long d2 = (n-tem)/104;
cout << (long long)x - 2ll*d2 << " " << (long long)y - 2ll*d2 << endl;
return 0;
}
}
cout << x << " " << y << endl;
}
B
答案是\(\sum _i \text{i步之后仍然没有结束的概率}\)。这个是一个等比数列。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9+7;
inline int add(int a,int b){a+=b;return a>=mod?a-mod:a;}
inline int sub(int a,int b){a-=b;return a<0?a+mod:a;}
inline int mul(int a,int b){return 1ll*a*b%mod;}
inline int qpow(int a,int b){int ret=1;for(;b;b>>=1,a=mul(a,a))if(b&1)ret=mul(ret,a);return ret;}
/* math */
const int N = 5e6+5;
int p[N],n,a,b,c;
int main()
{
cin >> n ;
cin >> p[1] >> a >> b >> c;
for(int i=2;i<=n;i++)p[i] = add(c,add(mul(b,p[i-1]), mul(mul(p[i-1],p[i-1]),a)));
for(int i=2;i<n;i++)p[n*2-i]=p[i];
int p2 = 1, totp = 0;
for(int i=1;i<2*n-1;i++){
// cout << p[i] << " " ;
totp = add(totp, mul(p2, sub(1,p[i])));
p2 = mul(p2, sub(1,p[i]));
}
int ans = totp;
ans = mul(totp,qpow(sub(1,p2),mod-2));
cout << ans << endl;
}
C
分析一下会发现一个条边有贡献当且仅当两端子树都有一个点被选择了。
相当于子树内的点是一种颜色,子树外是另外一种。
维护连续颜色段,启发式合并就行了。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9+7;
inline int add(int a,int b){a+=b;return a>=mod?a-mod:a;}
inline int sub(int a,int b){a-=b;return a<0?a+mod:a;}
inline int mul(int a,int b){return 1ll*a*b%mod;}
inline int qpow(int a,int b){int ret=1;for(;b;b>>=1,a=mul(a,a))if(b&1)ret=mul(ret,a);return ret;}
/* math */
int n;
const int N = 2e5+5;
int hed[N],to[N],nxt[N],cnt;
inline void adde(int u,int v){
++cnt;to[cnt]=v,nxt[cnt]=hed[u];hed[u]=cnt;
}
int id[N];
inline long long S(long long x){
return x*(x+1)/2;
}
struct Node{
long long ret;
map<int,pair<int,int> > info;
set<int> st;
inline void ins(int x){
st.insert(x);
set<int>::iterator t = st.find(x), lst = t, nxt = t;
int l=0,r=n+1;
if(t!=st.begin())l = *(--lst);
if(x!=*st.rbegin()) r = *(++nxt);
ret -= S(r-l-1);
int lft = x,rgt = x;
if(l&&l==x-1){
lft = info[l].first;
ret-=S(l-lft+1);
}
if(r!=n+1&&r==x+1){
rgt = info[r].second;
ret-=S(rgt-r+1);
}
info[lft].second = rgt,info[rgt].first = lft;
ret += S(rgt-lft+1);
ret += S(r-1-x) + S(x-1-l);
}
};
Node nd[N];
inline void mrg(Node &a,Node &b){
set<int> :: iterator t = b.st.begin();
for(;t!=b.st.end();++t){
a.ins(*t);
}
}
int sz[N];
long long ans = 0;
inline void dfs(int x,int pre){
id[x] = x;
nd[x].ret = S(n);
nd[x].ins(x);
sz[x] = 1;
for(int i=hed[x];i;i=nxt[i]){
int v = to[i];if(v==pre)continue;
dfs(v,x);
int ths = id[x], nxt = id[v];
if(sz[x] < sz[v]){
swap(ths,nxt);
}
mrg(nd[ths],nd[nxt]);
id[x] = ths;
sz[x] += sz[v];
}
if(pre)ans += S(n) - nd[id[x]].ret;
}
int main()
{
cin >> n;
for(int i=1;i<n;i++){
int u,v;scanf("%d%d",&u,&v);
adde(u,v),adde(v,u);
}
dfs(1,0);
ans*=2;ans%=mod;
int ss = S(n)%mod;
cout << mul(ans, qpow(ss,mod-2)) << endl;
}
D
duliu ccz
把线段按照斜率 $>0 / <0 $ 分组。
先拆成四组询问,全部包含的线可以轻松扫描线。现在分别考虑与纵轴相交的和与y轴相交的。因为线段不交,这些点都在一段区间。拆式子用平衡树维护就行了。
然后写题时间 \(8:00 \to 15:00\)。我才不会告诉你我炸int调了3h
#include<bits/stdc++.h>
using namespace std;
typedef double db;
const int N = 4e5+5;
int n,m;
namespace sgt{
#define lowbit(x) ((x)&(-x))
db tag[2000002];int cnt,rt;
inline void ins(int x,db s){
for(;x<=2000000;x+=lowbit(x)){
tag[x]+=s;
}
}
inline db qry(int x){
db ans = 0;
while(x){
ans+=tag[x];
x-=lowbit(x);
}return ans;
}
inline void clr(){
for(int i=1;i<=2000000;i++)tag[i]=0;
}
}
db sqr(db a){
return a*a;
}
struct Line{
int x1,y1,x2,y2;
bool operator < (const Line b)const{
return (y2-y1)/(x2-x1)<(b.y2-b.y1)/(b.x2-b.x1);
}
db cal(int id){return (db)(y2-y1)*(db)(id-x1)/(db)(x2-x1) + (db)y1;}
db Sin(){return (db)sqrt((db)sqr(y2-y1)+sqr(x2-x1))/(db)(x2-x1);}
db len(){return (db)sqrt((db)sqr(y2-y1)+sqr(x2-x1));}
}l[N],l2[N];
int D = 0;
namespace Bt{
int curx;
struct splaynode{
int ch[2],fa;db x,sx,x2,sx2;
}t[N];
int null=0,root;
inline bool son(int x){return t[t[x].fa].ch[1]==x;}
inline bool isroot(int x){return t[t[x].fa].ch[1]!=x&&t[t[x].fa].ch[0]!=x;}
inline void pushup(int x){
t[x].sx=t[x].x+t[t[x].ch[0]].sx+t[t[x].ch[1]].sx;
t[x].sx2=t[x].x2+t[t[x].ch[0]].sx2+t[t[x].ch[1]].sx2;
}
inline void rotate(int x){
int f=t[x].fa,gf=t[t[x].fa].fa;
bool a=son(x),b=son(x)^1;
if(!isroot(f))t[gf].ch[son(f)]=x;
t[x].fa=gf;
t[f].ch[a]=t[x].ch[b];t[t[x].ch[b]].fa=f;
t[x].ch[b]=f;t[f].fa=x;
pushup(f);pushup(x);//"pushup
}inline void dfs(int x){
if(!x)return ;
dfs(t[x].ch[0]);
cout <<'[' << x << " " << l[x].cal(curx) << ']'<< " ,";
dfs(t[x].ch[1]);
}
inline void print(){
dfs(root);puts("");
}
inline void splay(int x){
while(!isroot(x)){
int f=t[x].fa;
if(!isroot(f)){
if(son(f)^son(x))rotate(x);
else rotate(f);
}
rotate(x);
}
root=x;
}
inline void splay2(int x){
while(t[x].fa!=root){
int f=t[x].fa;
if(t[f].fa!=root){
if(son(f)^son(x))rotate(x);
else rotate(f);
}
rotate(x);
}
}
bool comp(int a,int b){
return l[a].cal(curx)<l[b].cal(curx);
}
bool cmp2(int a,int b){
int d = curx - l[a].x1;
int dy = l[a].y2-l[a].y1;
int dx = l[a].x2-l[a].x1;
int dt = b-l[a].y1;
// cout << l[a].x1 << " " << l[a].x2 << " " << l[a].y1 << " " << l[a].y2 << " " << curx << ":" << b << "|||";
// cout << d*dy << " " << dt*dx << endl;
if(!D)return 1ll*d*dy<=1ll*dt*dx;
else return 1ll*d*dy<1ll*dt*dx;
}
inline void del(int x){
// cout << "Delete" << " " << x << endl;
splay(x);
if(!t[x].ch[0]){root=t[x].ch[1],t[root].fa=0;return;}
if(!t[x].ch[1]){root=t[x].ch[0],t[root].fa=0;return;}
int lft = t[x].ch[0];while(t[lft].ch[1])lft = t[lft].ch[1];
int nxt = t[x].ch[1];while(t[nxt].ch[0])nxt = t[nxt].ch[0];
splay(lft);
splay2(nxt);
t[nxt].ch[0]=null;
pushup(nxt),pushup(lft);
// print();
}
inline int query(int x,int yline){
int id = root,ans = -1;
while(id){
bool side = cmp2(id,yline);
if(side)ans = id;
id = t[id].ch[side];
}
return ans;
}
inline void ins(int x){
if(!root){root = x;}else{
int lst = query(root,l[x].y1);
if(lst==-1){t[x].ch[1]=root,t[root].fa=x;root=x,pushup(x);}
else{
splay(lst);
int nxt = t[root].ch[1];
if(!nxt){t[root].ch[1]=x,t[x].fa = root,pushup(root);}
else{
while(t[nxt].ch[0])nxt=t[nxt].ch[0];
splay2(nxt);
t[nxt].ch[0]=x;t[x].fa=nxt;
pushup(nxt),pushup(root);
}
}
}
// cout << "ins" << x << endl;
// print();
}
void clr(){
for(int i=1;i<N;i++)t[i].ch[0]=t[i].ch[1]=t[i].fa=0,t[i].x=t[i].sx=t[i].x2=t[i].sx2=0;
root=0;curx=-1e9;
}
}
struct query{
int x,y,id,d;
query(int x=0,int y=0,int id=0,int d=0):x(x),y(y),id(id),d(d){}
bool operator < (const query b)const{return x<b.x;}
}q[N<<3];
struct op{
int x,y,id,d;
op(int x=0,int y=0,int id=0,int d=0):x(x),y(y),id(id),d(d){}
bool operator < (const op b)const{return x==b.x?(d<b.d):x<b.x;}
}o[N<<2];int tcnt;
inline void perform(int x){
// cout << "per" << " " << o[x].id << " " << o[x].d << endl;
Bt::curx = o[x].x;
int id = o[x].id;
// cout << id << " " << l[id].Cos() << endl;
if(o[x].d==1){
Bt::t[id].x = l[id].Sin();
Bt::t[id].x2 = l[id].x1*l[id].Sin();
Bt::pushup(id);
Bt::ins(id);
}else{
Bt::del(id);
if(!D)sgt::ins(l[id].y2,l[id].len());
}
// Bt::print();
// puts("fin");
}
db ret[N];
inline void Query(int x){
Bt::curx = q[x].x;
// cout << "q" << D << ":;" << q[x].x << " " << q[x].y << "," << q[x].d << endl;
// Bt::print();
db ans1 = 0;
if(!D){ans1 += sgt::qry(q[x].y);}
// cout << ":" << ans1 << "..";
int id1 = Bt::query(Bt::root,q[x].y);
// cout << id1 << " " << ".." << endl;
using namespace Bt;
if(id1!=-1){
Bt::splay(id1);
int nxt = t[id1].ch[1];
t[id1].ch[1]=0;pushup(id1);
ans1+=(db)t[id1].sx*curx-t[id1].sx2;
t[id1].ch[1]=nxt;pushup(id1);
}
// printf("%.6lf\n",ans1);
ret[q[x].id] += (db)q[x].d*ans1;
// Bt::print();
// puts("--");
}
int _A[N],_B[N],_C[N],_D[N];
db tot = 0;
int main()
{
cin >> n;
for(int i=1;i<=n;i++){
scanf("%d%d%d%d",&l2[i].x1,&l2[i].y1,&l2[i].x2,&l2[i].y2);
if(l2[i].x1>l2[i].x2){
swap(l2[i].x1,l2[i].x2), swap(l2[i].y1,l2[i].y2);
}
tot += sqrt((db)sqr(l2[i].x1-l2[i].x2)+(db)sqr(l2[i].y1-l2[i].y2));
}
sort(l2+1,l2+n+1);
cin >> m;
//-----------------------------
D=0;
sgt::clr();Bt::clr();Bt::curx=-1e9;
for(int i=1;i<=m;i++){
int a,b,c,d;
scanf("%d%d%d%d",&a,&b,&c,&d);
_A[i]=a,_B[i]=b,_C[i]=c,_D[i]=d;
q[i*4-3] = query(a,b,i,1);
q[i*4-2] = query(c,d,i,1);
q[i*4-1] = query(a,d,i,-1);
q[i*4-0] = query(c,b,i,-1);
}
// cout << "???" << endl;
tcnt=0;for(int i=1;i<=n;i++){
l[i]=l2[i];
if(l2[i].y1 <= l2[i].y2){
o[++tcnt] = op(l[i].x1,l[i].y1,i,1);
o[++tcnt] = op(l[i].x2,l[i].y2,i,-1);
}
}
sort(q+1,q+m*4+1);sort(o+1,o+tcnt+1);
int tar = 1;
for(int d=1;d<=m*4;d++){
while(tar<=tcnt && o[tar].x <= q[d].x){
perform(tar);tar++;
}Query(d);
}
/////
D=1;
sgt::clr();Bt::clr();Bt::curx=-1e9;
for(int i=1;i<=m*4;i++)swap(q[i].x,q[i].y);
tcnt=0;for(int i=1;i<=n;i++){
l[i]=l2[i];
swap(l[i].x1,l[i].y1);
swap(l[i].x2,l[i].y2);
if(l2[i].y1 <= l2[i].y2){
o[++tcnt] = op(l[i].x1,l[i].y1,i,1);
o[++tcnt] = op(l[i].x2,l[i].y2,i,-1);
}
}
sort(q+1,q+m*4+1);sort(o+1,o+tcnt+1);
tar = 1;
for(int d=1;d<=m*4;d++){
while(tar<=tcnt && o[tar].x <= q[d].x){
perform(tar);tar++;
}Query(d);
}
//----------------------------------------
D=0;
sgt::clr();Bt::clr();Bt::curx=-1e9;
for(int i=1;i<=m;i++){
int a=_A[i],b=_B[i],c=_C[i],d=_D[i];
q[i*4-3] = query(-a,b,i,-1);
q[i*4-2] = query(-c,d,i,-1);
q[i*4-1] = query(-a,d,i,1);
q[i*4-0] = query(-c,b,i,1);
}
tcnt=0;for(int i=1;i<=n;i++){
l[i]=l2[i];
if(l2[i].y1>l2[i].y2){
l[i].x1=-l[i].x1,l[i].x2=-l[i].x2;
swap(l[i].x1,l[i].x2),swap(l[i].y1,l[i].y2);
o[++tcnt] = op(l[i].x1,l[i].y1,i,1);
o[++tcnt] = op(l[i].x2,l[i].y2,i,-1);
}
}
sort(q+1,q+m*4+1);sort(o+1,o+tcnt+1);
tar = 1;
for(int d=1;d<=m*4;d++){
while(tar<=tcnt && o[tar].x <= q[d].x){
perform(tar);tar++;
}Query(d);
}
/* CUTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT */
D=1;
sgt::clr();Bt::clr();Bt::curx=-1e9;
for(int i=1;i<=m*4;i++)swap(q[i].x,q[i].y);
tcnt=0;for(int i=1;i<=n;i++){
l[i]=l2[i];
if(l2[i].y1 > l2[i].y2){
l[i].x1=-l[i].x1,l[i].x2=-l[i].x2;
swap(l[i].x1,l[i].x2),swap(l[i].y1,l[i].y2);
swap(l[i].x1,l[i].y1);swap(l[i].x2,l[i].y2);
o[++tcnt] = op(l[i].x1,l[i].y1,i,1);
o[++tcnt] = op(l[i].x2,l[i].y2,i,-1);
}
}
sort(q+1,q+m*4+1);sort(o+1,o+tcnt+1);
tar = 1;
for(int d=1;d<=m*4;d++){
while(tar<=tcnt && o[tar].x <= q[d].x){
perform(tar);tar++;
}Query(d);
}
//-----------------------------
for(int i=1;i<=m;i++){
printf("%.8lf\n",1e-15+ret[i]/tot);
}
}