刚和队友组队,第一次一起vp,也为几天后的比赛做准备
https://codeforces.com/gym/102803/problem/A
给定四条曲线,有两个参数,求包围的面积,其中有两条是圆,有两条是反三角函数(下面是样例的图)
圆面积直接求。反三角函数转成三角函数直接积分即可
队友代码:
#include
#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;
}
https://codeforces.com/gym/102803/problem/B
一眼数据结构,直接交给队友了
队友代码:
#include
#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|1
bool 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;
}
https://codeforces.com/gym/102803/problem/C
给定一个字符串 S ( ∣ S ∣ ≤ 8 × 1 0 5 ) S(|S|\le8\times 10^5) S(∣S∣≤8×105),找到两个等长的串 A A A 和 B B B, 使得 S = A A … A B B … B A A … A a S=AA\dots ABB\dots BAA\dots Aa S=AA…ABB…BAA…Aa,其中 a a a 是 A A A 的一个前缀(可以为空),最小化 ∣ A ∣ |A| ∣A∣
枚举 ∣ A ∣ |A| ∣A∣,找到第一个不匹配的位置,即为 B B B,同样的操作找到连续 B B B 串的结尾,后面判断是否全为 A A A 。判断相等用 h a s h hash hash 即可,复杂度 O ( n log n ) O(n\log n) O(nlogn), log n \log n logn 是调和级数
代码:
#include
/*
#include
#include
#include
#include
#include
#include
#include
//*/
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<
}
// 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<
n=strlen(s+1);
init();
int stb;
for(int i=1;i<=n;i++)
{
// cerr<
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<
// cerr<
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<
while(p+i-1<=n&&get(p,p+i-1)==b) p+=i;
// cerr<
// cerr<
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;
}
https://codeforces.com/gym/102803/problem/D
给一个正方体和一个法向量确定的平面,求平面与长方体的棱的交点数量为3/4/5/6个的概率
就一个大讨论,分界点一定是长方体的顶点位于平面内的情况(队友nb!!!)
队友代码:
#include
#include
#include
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 _; // zero
num 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());
}
}
https://codeforces.com/gym/102803/problem/F
回合制游戏,每回合你先动。对面有 n ( n ≤ 1000 ) n(n\le 1000) n(n≤1000) 颗棋子,每回合都会朝前(你)移动一步。你有一颗棋子,每回合可以向前/后/左/右/左前/右前移动一步。求你最多可以吃掉几颗对面的棋子
首先先简化操作。我们发现在正常情况下后退是没用的,因为你不会走到一颗棋子的后面,不然你上一回合就已经把它吃掉了(除非初始情况,一开始判断掉),这样你就不会后退了。
然后可以发现,我们一定是优先横向移动棋子,因为对方棋子的相对位置是不变的,所以我们没必要向前主动地去吃棋子,等对面送上来就行了。
这样就有一个问题,我们每回合必须得移动棋子,不能停在原地,这有点难受。我们可以花两回合停在原地,即先左再右,想要做到一回合不动还是不行,但我们可以替换掉原来的横向移动操作,以向左为例,我们可以先向左前再向后,这样原本一步向左变成了两步向左,实现了一步停留,向前、向右同理。
最后,按照上述的结论,越靠前的棋子越先被吃, d p dp dp 即可。复杂度 O ( n 2 ) O(n^2) O(n2)
队友代码:
#include
#include
#include
#define REP(i, n) for (int i = 0; i < n; i++)
#define pii std::pair<int, int>
#define xx first
#define yy second
const 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;
}
https://codeforces.com/gym/102803/problem/G
两个人玩游戏。给定一个 n ( n ≤ 1 0 5 ) n(n\le10^5) n(n≤105),每次操作可以取一个当前数的非平凡因子(非 1 1 1 和本身的因子,题目中说的真因子,但给的定义是对的)替代当前数,不能操作的人获胜,问先手是否获胜,如果获胜输出应该取的最大的数(直接获胜输出 0 0 0)。多测 T ≤ 1 0 3 T\le 10^3 T≤103
脑筋急转弯,暴力预处理即可,复杂度 O ( n n ) O(n\sqrt n) O(nn)
队友代码:
#include
#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;
}
https://codeforces.com/gym/102803/problem/H
σ k ( n ) = ∑ d ∣ n d k \sigma_k(n)=\sum_{d|n}d^k σk(n)=d∣n∑dk
给定 0 ≤ a , b < 4 , 1 ≤ n ≤ 1 0 12 0\le a,b<4,\;1\le n\le 10^{12} 0≤a,b<4,1≤n≤1012,求
( ( ∑ i = 1 n σ a ( i ) ) ⊕ ( ∑ i = 1 n σ b ( i ) ) ) m o d 2 64 ((\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 = 1 n σ k ( i ) = ∑ i = 1 n ∑ d ∣ i d k = ∑ d = 1 n d k ∑ d ∣ i 1 = ∑ d = 1 n d k ⋅ ⌊ n d ⌋ \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∑nd∣i∑dk=d=1∑ndkd∣i∑1=d=1∑ndk⋅⌊dn⌋
一个整除分块再加一个 0 / 1 / 2 / 3 0/1/2/3 0/1/2/3 次方前缀和就做完了
队友代码:(可能写法有点不太一样)
#include
#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;
}
https://codeforces.com/gym/102803/problem/K
有一棵树,给定所有点深度 d d d 和 b f s bfs bfs 序的排名区间 [ 1 , x ] [1,x] [1,x],求有多少颗满足限制的树
(算法是我后来yy出来的,可能和代码不太一样)
首先, b f s bfs bfs 序是按深度排的,可以先算出每个深度的标号范围,层内的标号互不影响。
其次,层间的父子关系和层内的标号可以分开计算(父子关系插个板就好了)。
最后,层内可以按 x x x 从小到大排序后一个个安排即可
队友代码:
#include
#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;
}
https://codeforces.com/gym/102803/problem/L
以 ( 0 , 0 ) (0,0) (0,0) 为起点 b f s bfs bfs,每个点的编号为 b f s bfs bfs 序,求给定 b f s bfs bfs 序对应的点坐标或给定点坐标对应的 b f s bfs bfs 序,强制在线,多测 T ≤ 1 0 4 T\le 10^4 T≤104
(Due to some zz reason, WA/T了4发)
按哈密顿距离分层,每层 4 n 4n 4n 个( n n n 为哈密顿距离)。层内顺序为上左(第一象限),上右(第二象限),右下(第四象限),下左(第三象限)。
给定 b f s bfs bfs 序找层的时候要二分(别问我怎么知道的)
代码:
#include
/*
#include
#include
#include
#include
#include
#include
#include
//*/
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<<" "<
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!!!(有队友做大代码手就是爽)