The 15th Heilongjiang Provincial Collegiate Programming Contest题解 gym102803

  • 前言
  • 题目
    • A. August
    • B. Bills of Paradise
    • C. Cornelia Street
    • D. Death by Thousand Cuts
    • F. False God
    • G. Goodbye
    • H. Hate That You Know Me
    • K. Keeping A Secret
    • L. Let's Get Married
  • 总结

前言

刚和队友组队,第一次一起vp,也为几天后的比赛做准备

题目

A. August

https://codeforces.com/gym/102803/problem/A

给定四条曲线,有两个参数,求包围的面积,其中有两条是圆,有两条是反三角函数(下面是样例的图)

圆面积直接求。反三角函数转成三角函数直接积分即可
队友代码:

#include<bits/stdc++.h>
#define N
using namespace std;
bool cur1;
int n;
inline void Rd(int &res){char c;res=0;while(c=getchar(),c<48);do res=(res<<3)+(res<<1)+(c^48);while(c=getchar(),c>47);return;
}
bool cur2;
int main(){//  printf("%lf MB\n",(&cur2-&cur1)/1024.0/1024);
//  freopen("data.txt","r",stdin);int T;Rd(T);while(T--){int a,b;Rd(a);Rd(b);double pi=acos(-1);printf("%lf\n",4.0*a*b+pi*a*a);}return 0;
}

B. Bills of Paradise

https://codeforces.com/gym/102803/problem/B
一眼数据结构,直接交给队友了
队友代码:

#include<bits/stdc++.h>
#define N 1000005
using namespace std;
bool cur1;
int n,q;
unsigned long long k1, k2;
long long a[N];
inline unsigned long long xorShift128Plus() {unsigned long long k3 = k1, k4 = k2;k1 = k4;k3 ^= k3 << 23;k2 = k3 ^ k4 ^ (k3 >> 17) ^ (k4 >> 26);return k2 + k4;
}
inline void Rd(int &res){char c;res=0;while(c=getchar(),c<48);do res=(res<<3)+(res<<1)+(c^48);while(c=getchar(),c>47);return;
}
inline int get1(long long x){int l=1,r=n,res=-1;while(l<=r){int mid=(l+r)>>1;if(a[mid]>=x)res=mid,r=mid-1;else l=mid+1;}return res;
}
inline int get2(long long x){int l=1,r=n,res=-1;while(l<=r){int mid=(l+r)>>1;if(a[mid]<=x)res=mid,l=mid+1;else r=mid-1;}return res;
}
struct YDtree{#define ls p<<1#define rs p<<1|1bool hv[N<<2],flag[N<<2];long long sum[N<<2],len[N<<2];inline void up(int p){sum[p]=sum[ls]+sum[rs];hv[p]=hv[ls]|hv[rs];}inline void down(int p){if(flag[p]){flag[ls]=flag[rs]=1;hv[ls]=hv[rs]=1;sum[ls]=len[ls];sum[rs]=len[rs];flag[p]=0;}}void build(int l,int r,int p){if(l==r){sum[p]=len[p]=a[l];hv[p]=1;return;}int mid=(l+r)>>1;build(l,mid,ls);build(mid+1,r,rs);len[p]=len[ls]+len[rs];up(p);}long long quiry1(int l,int r,int L,int R,int p){if(!hv[p])return -1;if(l==r)return a[l];down(p);int mid=(l+r)>>1;if(!hv[ls]||mid<L)return quiry1(mid+1,r,L,R,rs);long long h=quiry1(l,mid,L,R,ls);if(h==-1){if(mid<R)return quiry1(mid+1,r,L,R,rs);return -1;}return h;}bool update2(int l,int r,int L,int R,int p){if(!hv[p])return false;if(l==r){sum[p]=0;hv[p]=0;return true;}down(p);bool res;int mid=(l+r)>>1;if(!hv[ls]||mid<L)res=update2(mid+1,r,L,R,rs);else{res=update2(l,mid,L,R,ls);if(!res){if(mid<R)res=update2(mid+1,r,L,R,rs);}}up(p);return res;}long long quiry3(int l,int r,int L,int R,int p){if(L<=l&&r<=R)return sum[p];down(p);int mid=(l+r)>>1;long long res=0;if(mid>=L)res=quiry3(l,mid,L,R,ls);if(mid<R)res+=quiry3(mid+1,r,L,R,rs);return res;}void update4(int l,int r,int L,int R,int p){if(L<=l&&r<=R){flag[p]=1;sum[p]=len[p];hv[p]=1;return;}down(p);int mid=(l+r)>>1;if(mid>=L)update4(l,mid,L,R,ls);if(mid<R)update4(mid+1,r,L,R,rs);up(p);}
}YD;
bool cur2;
int main(){//  printf("%lf MB\n",(&cur2-&cur1)/1024.0/1024);
//  freopen("data.txt","r",stdin);scanf("%d %llu %llu", &n, &k1, &k2);for (int i = 1; i <= n; i++) a[i] = xorShift128Plus() % 999999999999 + 1;sort(a+1,a+n+1);YD.build(1,n,1);Rd(q);for(int i=1;i<=q;i++){char str[3];long long x;scanf("%s %lld",str,&x);if(str[0]=='F'){int h=get1(x);if(h==-1)puts("1000000000000");else{long long res=YD.quiry1(1,n,h,n,1);if(res==-1)puts("1000000000000");else printf("%lld\n",res);}}else if(str[0]=='D'){int h=get1(x);if(h==-1)continue;YD.update2(1,n,h,n,1);}else if(str[0]=='C'){int h=get2(x);if(h==-1)puts("0");else printf("%lld\n",YD.quiry3(1,n,1,h,1));}else{int h=get2(x);if(h==-1)continue;YD.update4(1,n,1,h,1);}}return 0;
}

C. Cornelia Street

https://codeforces.com/gym/102803/problem/C
给定一个字符串 S(∣S∣≤8×105)S(|S|\le8\times 10^5)S(∣S∣≤8×105),找到两个等长的串 AAA 和 BBB, 使得 S=AA…ABB…BAA…AaS=AA\dots ABB\dots BAA\dots AaS=AA…ABB…BAA…Aa,其中 aaa 是 AAA 的一个前缀(可以为空),最小化 ∣A∣|A|∣A∣

枚举 ∣A∣|A|∣A∣,找到第一个不匹配的位置,即为 BBB,同样的操作找到连续 BBB 串的结尾,后面判断是否全为 AAA 。判断相等用 hashhashhash 即可,复杂度 O(nlog⁡n)O(n\log n)O(nlogn), log⁡n\log nlogn 是调和级数
代码:

#include<bits/stdc++.h>
/*
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
//*/
using namespace std;
typedef long long ll;
typedef double db;
const int N=1000010,M=1000010,P=1e9+7;
const int p1=1e9+9,p2=998244353;
const int inf=0x3f3f3f3f;
const int INF=0xcfcfcfcf;
const db eps=1e-9,pi=2*asin(1);
template<typename tn> void read(tn &n);
template<typename tn1,typename tn2> bool cmax(tn1 &x,tn2 y) { return x<y?x=y,true:false; }
template<typename tn1,typename tn2> bool cmin(tn1 &x,tn2 y) { return x>y?x=y,true:false; }
#define mp(x,y) make_pair(x,y)
#define pii pair<int,int>
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pll pair<ll,ll>
int ADD(int x,int y,int p=P) { return x+y>=p?x+y-p:x+y; }
int MINUS(int x,int y,int p=P) { return x-y<0?x-y+p:x-y; }
#define plus(a,b) a=ADD(a,b)
#define minus(a,b) a=MINUS(a,b)
#define mul(a,b) a=1ll*(a)*(b)%P
#define mem(a,b) memset(a,b,sizeof(a))int BASE=129;
int n;
int h1[N],h2[N];
int m1[N],m2[N];
char s[N];void init()
{m1[0]=m2[0]=1;for(int i=1;i<=n;i++){int ch=s[i]+1;h1[i]=(1ll*h1[i-1]*BASE+ch)%p1;h2[i]=(1ll*h2[i-1]*BASE+ch)%p2;m1[i]=1ll*m1[i-1]*BASE%p1;m2[i]=1ll*m2[i-1]*BASE%p2;// cerr<<h1[i]<<" ";}// cerr<<"\n";
}
pii get(int l,int r)
{return mp(((h1[r]-1ll*h1[l-1]*m1[r-l+1])%p1+p1)%p1,((h2[r]-1ll*h2[l-1]*m2[r-l+1])%p2+p2)%p2);
}template<typename tn> void read(tn &n)
{tn s=0,flag=1;char ch=getchar();for(;ch<'0'||ch>'9';ch=getchar()) if(ch=='-') flag=-1;for(;'0'<=ch&&ch<='9';ch=getchar()) s=s*10+ch-'0';if(ch=='.'){ch=getchar();tn r=0,R=1;for(;'0'<=ch&&ch<='9';ch=getchar()) r=r*10+ch-'0',R*=10;s+=r/R;}n=s*flag;
}int main()
{scanf("%s",s+1);// cerr<<s+1<<"\n";n=strlen(s+1);init();int stb;for(int i=1;i<=n;i++){// cerr<<i<<": \n";pii a,b;a=get(1,i);int p=i+1;while(p+i-1<=n&&get(p,p+i-1)==a) p+=i;// cerr<<a.first<<" "<<a.second<<" "<<get(p,p+i-1).first<<" "<<get(p,p+i-1).second<<"\n";// cerr<<p<<"\n";if(p+i-1>n&&get(p,n)==get(1,n-p+1)){for(int j=1;j<=i;j++) putchar(s[j]);putchar(' ');for(int j=p-i;j<=p-1;j++) putchar(s[j]);putchar('\n');return 0;}b=get(p,p+i-1),stb=p;// cerr<<p<<" "<<stb<<"\n";while(p+i-1<=n&&get(p,p+i-1)==b) p+=i;// cerr<<b.first<<" "<<b.second<<" "<<get(p,p+i-1).first<<" "<<get(p,p+i-1).second<<"\n";// cerr<<p<<"\n";while(p+i-1<=n&&get(p,p+i-1)==a) p+=i;if(get(p,n)==get(1,n-p+1)){for(int j=1;j<=i;j++) putchar(s[j]);putchar(' ');for(int j=stb;j<=stb+i-1;j++) putchar(s[j]);putchar('\n');return 0;}// cerr<<"\n";}return 0;
}

D. Death by Thousand Cuts

https://codeforces.com/gym/102803/problem/D
给一个正方体和一个法向量确定的平面,求平面与长方体的棱的交点数量为3/4/5/6个的概率

就一个大讨论,分界点一定是长方体的顶点位于平面内的情况(队友nb!!!)
队友代码:

#include <algorithm>
#include <cstdio>
#include <vector>long long gcd(long long a, long long b) {return b ? gcd(b, a % b) : a;
}const int P = int(1e9) + 7;long long pow(long long a, long long b) {long long r = 1;while (b) {if (b & 1) r = r * a % P;b >>= 1;a = a * a % P;}return r;
}long long int_inv(long long x) {return pow(x, P - 2);
}/* a/b */
struct num {long long a, b;num(): a(0), b(1) {}num(long long t): a(t), b(1) {}num(long long a, long long b): a(a), b(b) {simp();}void read() {long long t;scanf("%lld", &t);*this = num(t);}long long print() {long long q = a, p = b;return 1ll * q * int_inv(p) % P;}void dump() {printf("%lld/%lld ", a, b);}void simp() {if (b < 0) {a = -a;b = -b;}long long g = gcd(a, b);a /= g;b /= g;}num operator-() {return num(-a, b);}num inv() {return num(b, a);}friend num operator+(num x, num y) {return num(x.a * y.b + x.b * y.a,x.b * y.b);}friend num operator-(num x, num y) {return x + -y;}friend num operator*(num x, num y) {return num(x.a * y.a,x.b * y.b);}friend num operator/(num x, num y) {return x * y.inv();}friend bool operator==(num x, num y) {return x.a == y.a && x.b == y.b;}friend bool operator<(num x, num y) {num z = x - y;if (z.a == 0) return false;return (z.a < 0) ^ (z.b < 0);}friend bool operator<=(num x, num y) {return x < y || x == y;}bool in_0_1() {return a >= 0 && a <= b;}
};int T;
num a, b, c, A, B, C;num _; // zeronum ans[10]; // ans[3..6];std::vector<num> v;num solve_d(num x, num y, num z) {return -(A * x + B * y + C * z);
}// int is_cross(num D, num x0, num y0, num z0, num dx, num dy, num dz) {//     // x = dx*t + x0 ...//     // A * (dx*t + x0) + ... + D == 0//     // num t = -(
//     //     (D + A*x0 + B*y0 + C*z0) / (A * dx + B * dy + C * dz)
//     // );//     return (-((D + A*x0 + B*y0 + C*z0) / (A * dx + B * dy + C * dz))).in_0_1();
// }#define is_cross(D, x0, y0, z0, dx, dy, dz) ((-((D + A*x0 + B*y0 + C*z0) / (A * dx + B * dy + C * dz))).in_0_1())int main() {scanf("%d", &T);while (T--) {a.read();b.read();c.read();A.read();B.read();C.read();v.clear();v.push_back(solve_d(_, _, _));v.push_back(solve_d(_, _, c));v.push_back(solve_d(_, b, _));v.push_back(solve_d(_, b, c));v.push_back(solve_d(a, _, _));v.push_back(solve_d(a, _, c));v.push_back(solve_d(a, b, _));v.push_back(solve_d(a, b, c));std::sort(v.begin(), v.end());// for (auto &z : v) {//     z.dump();//     printf("\n");// }for (int i = 3; i <= 6; i++) {ans[i] = num(0);}num minD = v[0], maxD = v[7];for (int i = 0; i <= 6; i++) {int j = i + 1;if (v[i] == v[j]) continue;num D = (v[i] + v[j]) / num(2);int cross = 0;cross += is_cross(D, _, _, _, a, _, _);cross += is_cross(D, _, _, _, _, b, _);cross += is_cross(D, a, _, _, _, b, _);cross += is_cross(D, _, b, _, a, _, _);cross += is_cross(D, _, _, _, _, _, c);cross += is_cross(D, a, _, _, _, _, c);cross += is_cross(D, _, b, _, _, _, c);cross += is_cross(D, a, b, _, _, _, c);cross += is_cross(D, _, _, c, a, _, _);cross += is_cross(D, _, _, c, _, b, _);cross += is_cross(D, a, _, c, _, b, _);cross += is_cross(D, _, b, c, a, _, _);// printf("D=[");// v[i].dump();// printf("..");// v[j].dump();// printf("] (avg=");// D.dump();// printf(") cross=%d\n", cross);ans[cross] = ans[cross] + (v[j] - v[i]) / (maxD - minD);}printf("%lld %lld %lld %lld\n", ans[3].print(), ans[4].print(), ans[5].print(), ans[6].print());}
}

F. False God

https://codeforces.com/gym/102803/problem/F
回合制游戏,每回合你先动。对面有 n(n≤1000)n(n\le 1000)n(n≤1000) 颗棋子,每回合都会朝前(你)移动一步。你有一颗棋子,每回合可以向前/后/左/右/左前/右前移动一步。求你最多可以吃掉几颗对面的棋子

首先先简化操作。我们发现在正常情况下后退是没用的,因为你不会走到一颗棋子的后面,不然你上一回合就已经把它吃掉了(除非初始情况,一开始判断掉),这样你就不会后退了。
然后可以发现,我们一定是优先横向移动棋子,因为对方棋子的相对位置是不变的,所以我们没必要向前主动地去吃棋子,等对面送上来就行了。
这样就有一个问题,我们每回合必须得移动棋子,不能停在原地,这有点难受。我们可以花两回合停在原地,即先左再右,想要做到一回合不动还是不行,但我们可以替换掉原来的横向移动操作,以向左为例,我们可以先向左前再向后,这样原本一步向左变成了两步向左,实现了一步停留,向前、向右同理。
最后,按照上述的结论,越靠前的棋子越先被吃, dpdpdp 即可。复杂度 O(n2)O(n^2)O(n2)
队友代码:

#include <algorithm>
#include <cstdio>
#include <cstring>#define REP(i, n) for (int i = 0; i < n; i++)#define pii std::pair<int, int>
#define xx first
#define yy secondconst int N = 1003;int T, xx0, yy0, n;
pii p[N];int f[N];int cmp(pii &a, pii &b) {if (a.yy != b.yy) return b.yy > a.yy;return b.xx > a.xx;
}int main() {scanf("%d", &T);while (T--) {memset(f, 0x87, sizeof f);scanf("%d%d%d", &xx0, &yy0, &n);int tag = 0;REP(i, n) {scanf("%d%d", &p[i].xx, &p[i].yy);tag |= p[i].xx == xx0 && p[i].yy == yy0-1;}if (!tag) {p[n].xx = xx0;p[n].yy = yy0-1;n++;}std::sort(p, p+n, cmp);int ans = 0;pii *pp = std::find(p, p + n, pii{xx0, yy0-1});if (tag) {f[pp-p]=1;// printf("%d,%d :: 1\n", xx0, yy0-1);} else {f[pp-p]=0;// printf("%d,%d :: 0\n", xx0, yy0-1);}for (int i = 0; i < n; i++) {for (int j = 0; j < i; j++) {if (p[j].yy > p[i].yy) continue;if (p[j].yy == p[i].yy) continue;if (abs(p[i].xx - p[j].xx) > p[i].yy - p[j].yy + 1) continue;// printf("+ %d,%d -> %d,%d :: %d\n", p[j].xx, p[j].yy, p[i].xx, p[i].yy, f[j]+1);if (f[j]+1 > f[i]) {f[i] = f[j]+1;}ans = std::max(ans, f[i]);}}printf("%d\n", ans);}return 0;
}

G. Goodbye

https://codeforces.com/gym/102803/problem/G
两个人玩游戏。给定一个 n(n≤105)n(n\le10^5)n(n≤105),每次操作可以取一个当前数的非平凡因子(非 111 和本身的因子,题目中说的真因子,但给的定义是对的)替代当前数,不能操作的人获胜,问先手是否获胜,如果获胜输出应该取的最大的数(直接获胜输出 000)。多测 T≤103T\le 10^3T≤103

脑筋急转弯,暴力预处理即可,复杂度 O(nn)O(n\sqrt n)O(nn​)
队友代码:

#include<bits/stdc++.h>
#define N 233333
using namespace std;
bool cur1;
int n;
inline void Rd(int &res){char c;res=0;while(c=getchar(),c<48);do res=(res<<3)+(res<<1)+(c^48);while(c=getchar(),c>47);return;
}
int val[N];
void init(){int h=100000;for(int i=2;i<=h;i++){int cnt=0;val[i]=-1;for(int j=2;j*j<=i;j++)if(i%j==0){cnt++;if(val[j]==-1)val[i]=max(val[i],j);if(val[i/j]==-1)val[i]=max(val[i],i/j);}if(!cnt)val[i]=0;}
}
bool cur2;
int main(){//  printf("%lf MB\n",(&cur2-&cur1)/1024.0/1024);
//  freopen("data.txt","r",stdin);init();int T;Rd(T);while(T--){Rd(n);printf("%d\n",val[n]);}return 0;
}

H. Hate That You Know Me

https://codeforces.com/gym/102803/problem/H
σk(n)=∑d∣ndk\sigma_k(n)=\sum_{d|n}d^kσk​(n)=d∣n∑​dk
给定 0≤a,b<4,1≤n≤10120\le a,b<4,\;1\le n\le 10^{12}0≤a,b<4,1≤n≤1012,求
((∑i=1nσa(i))⊕(∑i=1nσb(i)))mod264((\sum_{i=1}^n\sigma_a(i))\oplus(\sum_{i=1}^n\sigma_b(i)))\mod 2^{64}((i=1∑n​σa​(i))⊕(i=1∑n​σb​(i)))mod264

眼瞎把 <<< 看成 ≤\le≤,导致队友推了一个四次方前缀和的通项(**出题人),浪费了好长时间(就说怎么那么多人会四次方前缀和的通项的)
⊕\oplus⊕ 两边的式子一样,只推一个即可
∑i=1nσk(i)=∑i=1n∑d∣idk=∑d=1ndk∑d∣i1=∑d=1ndk⋅⌊nd⌋\begin{aligned}\sum_{i=1}^n\sigma_k(i)&=\sum_{i=1}^n\sum_{d|i}d^k\\&=\sum_{d=1}^nd^k\sum_{d|i}1\\&=\sum_{d=1}^nd^k\cdot\lfloor\frac{n}{d} \rfloor \end{aligned}i=1∑n​σk​(i)​=i=1∑n​d∣i∑​dk=d=1∑n​dkd∣i∑​1=d=1∑n​dk⋅⌊dn​⌋​
一个整除分块再加一个 0/1/2/30/1/2/30/1/2/3 次方前缀和就做完了
队友代码:(可能写法有点不太一样)

#include<bits/stdc++.h>
#define ull unsigned long long
using namespace std;
bool cur1;
long long n;
inline void Rd(int &res){char c;res=0;while(c=getchar(),c<48);do res=(res<<3)+(res<<1)+(c^48);while(c=getchar(),c>47);return;
}
ull solve0(ull l,ull r){return r-l+1;}
ull calc1(ull a){if(a&1)return (a+1)/2*a;return a/2*(a+1);
}
ull solve1(ull l,ull r){return calc1(r)-calc1(l-1);
}
ull calc2(ull a){ull h1=a,h2=a+1,h3=2*a+1;if(h1&1)h2>>=1;else h1>>=1;if(h1%3==0)h1/=3;else if(h2%3==0)h2/=3;else h3/=3;return h1*h2*h3;
}
ull solve2(ull l,ull r){return calc2(r)-calc2(l-1);
}
ull calc3(ull a){return calc1(a)*calc1(a);
}
ull solve3(ull l,ull r){return calc3(r)-calc3(l-1);
}
ull solve(ull l,ull r,int f){if(f==0)return solve0(l,r);if(f==1)return solve1(l,r);if(f==2)return solve2(l,r);if(f==3)return solve3(l,r);
}
bool cur2;
int main(){//  printf("%lf MB\n",(&cur2-&cur1)/1024.0/1024);
//  freopen("data.txt","r",stdin);int a,b;scanf("%d%d%lld",&a,&b,&n);ull md=sqrt(n);ull res1=0,res2=0;for(int i=1;1ll*i*i<=n;i++){res1+=solve(i,i,a)*(n/i);res2+=solve(i,i,b)*(n/i);ull r=n/i,l=n/(i+1)+1;l=max(l,(ull)(i+1));res1+=solve(l,r,a)*i;res2+=solve(l,r,b)*i;
//      printf("%d %llu %llu\n",i,l,r);
//      printf("%d %llu %llu\n",i,res1,res2);}
//  printf("%llu %llu\n",res1,res2);printf("%llu\n",res1^res2);return 0;
}

K. Keeping A Secret

https://codeforces.com/gym/102803/problem/K
有一棵树,给定所有点深度 ddd 和 bfsbfsbfs 序的排名区间 [1,x][1,x][1,x],求有多少颗满足限制的树

(算法是我后来yy出来的,可能和代码不太一样)
首先,bfsbfsbfs 序是按深度排的,可以先算出每个深度的标号范围,层内的标号互不影响。
其次,层间的父子关系和层内的标号可以分开计算(父子关系插个板就好了)。
最后,层内可以按 xxx 从小到大排序后一个个安排即可
队友代码:

#include<bits/stdc++.h>
#define N 100005
#define mod 1000000007
using namespace std;
bool cur1;
int n;
struct node{int d,x;
}Q[N];
inline bool cmp(node a,node b){return a.d==b.d?a.x<b.x:a.d<b.d;
}
inline void Rd(int &res){char c;res=0;while(c=getchar(),c<48);do res=(res<<3)+(res<<1)+(c^48);while(c=getchar(),c>47);return;
}
long long fac[N],infac[N];
inline long long C(int x,int y){return fac[y]*infac[x]%mod*infac[y-x]%mod;
}
void init(){fac[0]=infac[1]=infac[0]=1;for(int i=1;i<=n;i++)fac[i]=fac[i-1]*i%mod;for(int i=2;i<=n;i++)infac[i]=mod-mod/i*infac[mod%i]%mod;for(int i=2;i<=n;i++)infac[i]=infac[i]*infac[i-1]%mod;
}
bool cur2;
int main(){//  printf("%lf MB\n",(&cur2-&cur1)/1024.0/1024);
//  freopen("data.txt","r",stdin);Rd(n);init();for(int i=1;i<=n;i++)Rd(Q[i].d),Rd(Q[i].x);sort(Q+1,Q+n+1,cmp);if((Q[1].d==1&&Q[2].d==1)||Q[1].d!=1){puts("0");return 0;}long long ans=1;for(int i=1,r,last=1;i<=n;i=r+1){r=i;while(r<n&&Q[r+1].d==Q[i].d)r++;if(i==1)continue;for(int j=i;j<=r;j++){int o=min(Q[j].x-j+1,r-j+1);if(o<1){puts("0");return 0;}ans=ans*o%mod;}ans=ans*C(last-1,r-i+last)%mod;last=r-i+1;}printf("%lld\n",ans);return 0;
}

L. Let’s Get Married

https://codeforces.com/gym/102803/problem/L
以 (0,0)(0,0)(0,0) 为起点 bfsbfsbfs,每个点的编号为 bfsbfsbfs 序,求给定 bfsbfsbfs 序对应的点坐标或给定点坐标对应的 bfsbfsbfs 序,强制在线,多测 T≤104T\le 10^4T≤104

(Due to some zz reason, WA/T了4发)
按哈密顿距离分层,每层 4n4n4n 个( nnn 为哈密顿距离)。层内顺序为上左(第一象限),上右(第二象限),右下(第四象限),下左(第三象限)。
给定 bfsbfsbfs 序找层的时候要二分(别问我怎么知道的)
代码:

#include<bits/stdc++.h>
/*
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
//*/
using namespace std;
typedef long long ll;
typedef double db;
const int N=100010,M=1000010,P=1e9+7;
const int inf=0x3f3f3f3f;
const int INF=0xcfcfcfcf;
const db eps=1e-9,pi=2*asin(1);
template<typename tn> void read(tn &n);
template<typename tn1,typename tn2> bool cmax(tn1 &x,tn2 y) { return x<y?x=y,true:false; }
template<typename tn1,typename tn2> bool cmin(tn1 &x,tn2 y) { return x>y?x=y,true:false; }
#define mp(x,y) make_pair(x,y)
#define pii pair<int,int>
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pll pair<ll,ll>
int ADD(int x,int y,int p=P) { return x+y>=p?x+y-p:x+y; }
int MINUS(int x,int y,int p=P) { return x-y<0?x-y+p:x-y; }
#define plus(a,b) a=ADD(a,b)
#define minus(a,b) a=MINUS(a,b)
#define mul(a,b) a=1ll*(a)*(b)%P
#define mem(a,b) memset(a,b,sizeof(a))template<typename tn> void read(tn &n)
{tn s=0,flag=1;char ch=getchar();for(;ch<'0'||ch>'9';ch=getchar()) if(ch=='-') flag=-1;for(;'0'<=ch&&ch<='9';ch=getchar()) s=s*10+ch-'0';if(ch=='.'){ch=getchar();tn r=0,R=1;for(;'0'<=ch&&ch<='9';ch=getchar()) r=r*10+ch-'0',R*=10;s+=r/R;}n=s*flag;
}int main()
{int n; read(n);ll xc=0,yc=0;for(int i=1;i<=n;i++){int opt; read(opt);if(opt==1){ll id; read(id);if(id==0){printf("%lld %lld\n",-xc,-yc);xc=0,yc=0;continue;}ll x,y;ll l=0,r=5e8;while(l+1<r){ll mid=l+r>>1;if(2ll*mid*(mid+1)<id) l=mid;else r=mid;}ll p=l+1;id-=2ll*p*(p-1);// cerr<<" "<<p<<" "<<id<<"\n";if(1<=id&&id<=2*p-1) // up + ?{if(id==1){x=p,y=0;}else{if(id&1) x=-id/2,y=p-id/2;else x=id/2,y=p-id/2;}}else if(2*p<=id&&id<=3*p-1) // right + down{id-=2*p;x=p-id,y=-id;}else if(3*p<=id&&id<=4*p) // down + left{id-=3*p;x=-id,y=id-p;}printf("%lld %lld\n",x-xc,y-yc);xc=x,yc=y;}else{ll x,y; read(x),read(y);ll p=abs(x)+abs(y);if(x==0&&y==0){printf("0\n");xc=0,yc=0;continue;}ll ans=2ll*p*(p-1);if(y>0){if(x==0) ans++;else if(x>0) ans+=2*x;else if(x<0) ans+=2*(-x)+1;}else if(x>0&&y<=0){ans+=2*p-y;}else if(x<=0&&y<=0){ans+=3*p-x;}printf("%lld\n",ans);xc=x,yc=y;}}return 0;
}
/*
1
2 -1 -1
*/
/*
1
1 79999999800000000
*/

总结

5h的比赛实际打了3h,由于只是队友之间的磨合,后面剩下三道难题都没花时间去做。
总结就是:队友nb!!!(有队友做大代码手就是爽)

The 15th Heilongjiang Provincial Collegiate Programming Contest题解 gym102803相关推荐

  1. The 15th Heilongjiang Provincial Collegiate Programming Contest (A、G、H、L)

    The 15th Heilongjiang Provincial Collegiate Programming Contest A. August G. Goodbye H. Hate That Yo ...

  2. The 15th Heilongjiang Provincial Collegiate Programming Contest(A,C,F,G,H,L)

    比赛链接 2021/2/7训练赛 Problem.A August 题解 不难发现上半部分是个半径为 a a a的圆,下半部分利用割补小正方形的方法得出等价于一个长为 2 a 2a 2a,宽为 2 b ...

  3. The 16th Heilongjiang Provincial Collegiate Programming Contest部分题解

    The 16th Heilongjiang Provincial Collegiate Programming Contest 目录 D - Doin' Time 题目思路 题目代码 F - Func ...

  4. The 15th Jilin Provincial Collegiate Programming Contest

    The 15th Jilin Provincial Collegiate Programming Contest A. Random Number Checker 签到 #include <bi ...

  5. 【ZJCPC2018 第15届 浙江省赛】The 15th Zhejiang Provincial Collegiate Programming Contest(MABLJK 6题)

    补题地址:https://zoj.pintia.cn/home/news 搜索15th 本文按照通过率补的题 M. Lucky 7 题意:如果存在从给出的长为n的序列中选择一个数+b 可以被7整除,就 ...

  6. 第十五届吉林省赛The 15th Jilin Provincial Collegiate Programming Contest C.Random Number Generator(数学 BSGS)

    文章目录 题意 题解 代码 总结 题目链接 题意 : 题解 : BSGS 代码 : #include <bits/stdc++.h> #include <unordered_map& ...

  7. 【21.10.24】The 15th Chinese Northeast Collegiate Programming Contest题解

    A. Matrix(组合数+数学) #include <bits/stdc++.h> using namespace std; #define mod 998244353 ll fac[1 ...

  8. The 15th Chinese Northeast Collegiate Programming Contest 题解(CCPC压力测试?

    CCPC压力测试用了这套题,和一个队友一起搞了.初期签到还算比较顺利,还碰到了挺多有意思的题目,做的好爽,但还是犯了很多低级错误,对于杭电要时时刻刻关同步或者scanf,并且写代码还是要仔细些. A. ...

  9. The 15th Chinese Northeast Collegiate Programming Contest部分题解

    The 15th Chinese Northeast Collegiate Programming Contest 目录 E. Easy Math Problem 题目思路 题目代码 I. Takea ...

最新文章

  1. call、apply和bind的原生实现
  2. idea加载lombok插件
  3. matlab中将ebn0转snr,EbNo(EbN0)和SNR
  4. ansys 常用结构单元类型
  5. HTML+CSS 制作下拉菜单
  6. R语言潜在变量模型、探索性因子分析EFA、验证性因素分析(CFA)、结构方程建模(SEM)之间的关系、潜在变量模型常用包:ltm包、sem包、OpenMx包、Lavaan包、lsa包、ca包等
  7. C语言的lsb算法bmp信息隐藏,基于LSB算法的图像信息隐藏与检测.docx
  8. 前端学习笔记 HTML5 保姆级教程
  9. We‘re sorry but XXX doesn‘t work properly without JavaScript enabled. Please enable it to contin
  10. C语言汉诺塔问题图文详解
  11. python floor是什么意思_简单介绍Python中的floor()方法
  12. Xcode 13.4.1如何显示文件拓展名
  13. linux 创建子进程,Linux中使用fork创建子进程详解及示例程序
  14. Python 练习实例100例—5
  15. c/c++ substr()函数
  16. 北漂95后的2020年
  17. codevs 2832 6个朋友 并查集 解题报告
  18. 徒手撸设计模式-抽象工厂模式
  19. linux操作系统:x86架构,一个良好的运营环境
  20. Codeforces Round #577 (Div. 2)--B. Zero Array

热门文章

  1. 浏览器中java在什么位置_win10浏览器安装位置在哪里_如何找到win10浏览器的安装路径...
  2. 中秋节支付宝口令红包解析
  3. 飞桨图像分类入门——多种网络模型在手写数字识别的应用
  4. NFT Insider #75:The Sandbox 为Avatar 打造特别活动,Ambire 团队发起第一次官方治理投票
  5. 论文阅读笔记:Jointly Discovering Visual Objects and Spoken Words from Raw Sensory Input
  6. 有限元仿真分析技术中网格划分的类型与步骤
  7. 国内首款智能网联无人迷你巴士在东南大学首发试运行,车内没有配置方向盘...
  8. Python安装docx依赖包
  9. android dlna uri,DLNA 在自己的APP 中添加投屏功能
  10. AI+金融驱动金融信创“芯”生态