KYOCERA Programming Contest 2021(AtCoder Beginner Contest 200) E - Patisserie ABC 2

news/2024/12/22 20:43:55/

KYOCERA Programming Contest 2021(AtCoder Beginner Contest 200) E - Patisserie ABC 2


题意

n 3 n^3 n3个三元组 ( i , j , k ) , 1 ≤ i , j , k ≤ n (i,j,k),1\le i,j,k\le n (i,j,k),1i,j,kn进行排序,问第 k k k个三元组是什么

排序先按总和 i + j + k i+j+k i+j+k进行排序,小的在前

相同和的情况下按 i → j → k i\rightarrow j\rightarrow k ijk的顺序比对大小,小的在前(字典序小的在前)




思路

打表找规律,先按和进行分组,可得对于前几个 n n n,和为 j ∈ [ 3 , 3 ∗ n ] j\in[3,3*n] j[3,3n]的三元组数量如下
n = 2 : 1 , 3 , 3 , 1 n = 3 : 1 , 3 , 6 , 7 , 6 , 3 , 1 n = 4 : 1 , 3 , 6 , 10 , 12 , 12 , 10 , 6 , 3 , 1 n = 5 : 1 , 3 , 6 , 10 , 15 , 18 , 19 , 18 , 15 , 10 , 6 , 3 , 1 n = 6 : 1 , 3 , 6 , 10 , 15 , 21 , 25 , 27 , 27 , 25 , 21 , 15 , 10 , 6 , 3 , 1 n = 7 : 1 , 3 , 6 , 10 , 15 , 21 , 28 , 33 , 36 , 37 , 36 , 33 , 28 , 21 , 15 , 10 , 6 , 3 , 1 \begin{aligned} n=2:&\ 1,3,3,1\\ n=3:&\ 1,3,6,7,6,3,1\\ n=4:&\ 1,3,6,10,12,12,10,6,3,1\\ n=5:&\ 1,3,6,10,15,18,19,18,15,10,6,3,1\\ n=6:&\ 1,3,6,10,15,21,25,27,27,25,21,15,10,6,3,1\\ n=7:&\ 1,3,6,10,15,21,28,33,36,37,36,33,28,21,15,10,6,3,1\\ \end{aligned} n=2:n=3:n=4:n=5:n=6:n=7: 1,3,3,1 1,3,6,7,6,3,1 1,3,6,10,12,12,10,6,3,1 1,3,6,10,15,18,19,18,15,10,6,3,1 1,3,6,10,15,21,25,27,27,25,21,15,10,6,3,1 1,3,6,10,15,21,28,33,36,37,36,33,28,21,15,10,6,3,1
由于呈左右对称规律,折半后表为(标红表示不进行对称处理)
n = 2 : 1 , 3 n = 3 : 1 , 3 , 6 , 7 n = 4 : 1 , 3 , 6 , 10 , 12 n = 5 : 1 , 3 , 6 , 10 , 15 , 18 , 19 n = 6 : 1 , 3 , 6 , 10 , 15 , 21 , 25 , 27 n = 7 : 1 , 3 , 6 , 10 , 15 , 21 , 28 , 33 , 36 , 37 \begin{aligned} n=2:&\ 1,\textcolor{green}{3}\\ n=3:&\ 1,3,\textcolor{green}{6},\textcolor{red}{7}\\ n=4:&\ 1,3,6,\textcolor{green}{10},12\\ n=5:&\ 1,3,6,10,\textcolor{green}{15},18,\textcolor{red}{19}\\ n=6:&\ 1,3,6,10,15,\textcolor{green}{21},25,27\\ n=7:&\ 1,3,6,10,15,21,\textcolor{green}{28},33,36,\textcolor{red}{37}\\ \end{aligned} n=2:n=3:n=4:n=5:n=6:n=7: 1,3 1,3,6,7 1,3,6,10,12 1,3,6,10,15,18,19 1,3,6,10,15,21,25,27 1,3,6,10,15,21,28,33,36,37
发现从第一个数到标绿的数字位置,之前每个数均为 1 + 2 + ⋯ + p 1+2+\cdots+p 1+2++p p p p表示位置),每次增幅即下标,直到下标为 n n n时截止

而从标绿数字的下一个数开始,每次增幅从 n − 2 n-2 n2开始依次递减 2 2 2

n = 7 n=7 n=7为例,第二个数到第七个数较前一个数的增幅为 + 2 , + 3 , + 4 , + 5 , + 6 , + 7 +2,+3,+4,+5,+6,+7 +2,+3,+4,+5,+6,+7,从第八个数开始变为 + 5 , + 3 , + 1 +5,+3,+1 +5,+3,+1

故根据上述规律,对于每组数据输入的 n n n,我们可以将**和为 s u m sum sum时的三元组数量 t m p [ s u m ] tmp[sum] tmp[sum]**预处理出

int i=3; //sum的范围为3*1~3*n
for(int j=1;j<=n;i++,j++)tmp[i]=tmp[i-1]+j; //前n个数,每次增幅为j=1~n
for(int j=n-2;j>0;i++,j-=2)tmp[i]=tmp[i-1]+j; //第n+1个数开始,每次增幅从n开始每次-2
if(n%2) //这里处理对称,分奇偶处理
{int m=i-1;for(;i<=3*n;i++)tmp[i]=tmp[m-(i-m)];
}
else
{int m=i;for(;i<=3*n;i++)tmp[i]=tmp[m-1-(i-m)];
}

根据上方的预处理,我们可以得出 n , k n,k n,k的限制下三元组 ( i , j , k ) (i,j,k) (i,j,k)的和 s u m sum sum为多少

ll sum=3;
while(k>tmp[sum])
{k-=tmp[sum];sum++;
}

由于相同和的情况下是按照字典序进行排序的, 所以可以按从小到大的顺序枚举第一个数 a a a,并得出后两个数相加之和 x = s u m − a x=sum-a x=suma

对于二元组 ( j , k ) , 1 ≤ j , k ≤ n , j + k = s u m (j,k),1\le j,k\le n,j+k=sum (j,k),1j,kn,j+k=sum的情况数

明显当 s u m ≤ n sum\le n sumn时,种类数只有 s u m − 1 sum-1 sum1种: ( 1 , s u m − 1 ) , ( 2 , s u m − 2 ) , ⋯ , ( s u m − 1 , 1 ) (1,sum-1),(2,sum-2),\cdots,(sum-1,1) (1,sum1),(2,sum2),,(sum1,1)

故对于 s u m ∈ [ 2 , n + 1 ] sum\in[2,n+1] sum[2,n+1],种类数为 1 , 2 , ⋯ , n 1,2,\cdots,n 1,2,,n

s u m > n sum\gt n sum>n时,种类数呈对称状逐级递减

即对于 s u m ∈ [ n + 2 , 2 n ] sum\in[n+2,2n] sum[n+2,2n],种类数为 n − 1 , n − 2 , ⋯ , 1 n-1,n-2,\cdots,1 n1,n2,,1

由于 n n n固定,这部分也可预处理成 t m p 2 tmp2 tmp2数组

rep(i,2,n+1)tmp2[i]=i-1;
rep(i,n+2,n+n)tmp2[i]=n*2+1-i;

于是枚举第一个数 a a a,若 k > t m p 2 [ s u m − a ] k\gt tmp2[sum-a] k>tmp2[suma],则第一个数比 a a a大,继续枚举下去且让 k − = t m p 2 [ s u m − a ] k-=tmp2[sum-a] k=tmp2[suma]

直到 k ≤ t m p 2 [ s u m − a ] k\le tmp2[sum-a] ktmp2[suma],此时 a a a便固定了下来,由于 n ≤ 1 0 6 n\le 10^6 n106,于是便可以直接枚举第二个数,求出第 k k k个合法方案输出即可




程序

//#include<ext/pb_ds/assoc_container.hpp>
//#include<ext/pb_ds/hash_policy.hpp>
#include<bits/stdc++.h>
#define closeSync ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define multiCase int T;cin>>T;for(int t=1;t<=T;t++)
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i<(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define perr(i,a,b) for(int i=(a);i>(b);i--)
#define all(a) (a).begin(),(a).end()
#define mst(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define eb emplace_back
using namespace std;
//using namespace __gnu_pbds;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> P;
const int INF=0x3f3f3f3f;
const ll LINF=0x3f3f3f3f3f3f3f3f;
const double eps=1e-12;
const double PI=acos(-1.0);
const ll mod=998244353;
mt19937 mt19937random(std::chrono::system_clock::now().time_since_epoch().count());
ll getRandom(ll l,ll r){return uniform_int_distribution<ll>(l,r)(mt19937random);}
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll qmul(ll a,ll b){ll r=0;while(b){if(b&1)r=(r+a)%mod;b>>=1;a=(a+a)%mod;}return r;}
ll qpow(ll a,ll n){ll r=1;while(n){if(n&1)r=(r*a)%mod;n>>=1;a=(a*a)%mod;}return r;}
ll qpow(ll a,ll n,ll p){ll r=1;while(n){if(n&1)r=(r*a)%p;n>>=1;a=(a*a)%p;}return r;}ll tmp[3000050],tmp2[2000050];void init(int n)
{int i=3;for(int j=1;j<=n;i++,j++)tmp[i]=tmp[i-1]+j;for(int j=n-2;j>0;i++,j-=2)tmp[i]=tmp[i-1]+j;if(n%2){int m=i-1;for(;i<=3*n;i++)tmp[i]=tmp[m-(i-m)];}else{int m=i;for(;i<=3*n;i++)tmp[i]=tmp[m-1-(i-m)];}rep(i,2,n+1)tmp2[i]=i-1;rep(i,n+2,n*2)tmp2[i]=n*2+1-i;
}void solve()
{int n;ll k;cin>>n>>k;init(n);ll sum=3;while(k>tmp[sum]){k-=tmp[sum];sum++;}rep(a,sum-2*n,sum-2){if(a<1)continue;int x=sum-a;if(k>tmp2[x])k-=tmp2[x];else{cout<<a<<' ';int b,c;if(x>=n+1)b=x-n,c=n;elseb=1,c=x-1;while(--k)b++,c--;cout<<b<<' '<<c<<'\n';assert(b>=1&&b<=n&&c>=1&&c<=n);return;}}
}
int main()
{closeSync;//multiCase{solve();}return 0;
}

https://www.cnblogs.com/stelayuri/p/14746795.html


http://www.ppmy.cn/news/913622.html

相关文章

KYOCERA Programming Contest 2021 (AtCoder Beginner Contest 200) A~E 题解

ABC200/KYOCERA2021 A~E [A - Century](https://atcoder.jp/contests/abc200/tasks/abc200_a)题目大意输入格式输出格式样例分析代码 [B - 200th ABC-200](https://atcoder.jp/contests/abc200/tasks/abc200_b)题目大意输入格式输出格式样例分析代码 [C - Ringos Favorite Numb…

KYOCERA Programming Contest 2021(AtCoder Beginner Contest 200)题解

文章目录 A - CenturyB - 200th ABC-200C - Ringos Favorite Numbers 2D - Happy Birthday! 2E - Patisserie ABC 2F - Minflip Summation KYOCERA Programming Contest 2021&#xff08;AtCoder Beginner Contest 200&#xff09; A - Century 简单的除以 200 200 200向上取…

KYOCERA Programming Contest 2022(AtCoder Beginner Contest 271)G.Access Counter(概率+矩阵快速幂优化dp)

题目 Takahashi布置了一个网页&#xff0c; 给定一个长为24的仅由A和T构成的字符串&#xff0c;表示每天整点能登进这个网页的概率 第i个字母如果是T&#xff0c;表示第i个整点的时候Takahashi有X(1<X<99)%的概率能登进去一次&#xff0c; 如果是A&#xff0c;表示第…

KYOCERA Programming Contest 2021(AtCoder Beginner Contest 200)E

首先考虑n^2的做法那就是 for(int i 1; i < 3; i){ for(int j 1; j < 3 * n; j){ for(int k 1; k < n; k){ dp[i][j k] dp[i - 1][j];我们从中可以看出 当 j 1的时候他对所有 j 1 ~ j n 那么 j 2 就对 j 2 ~ j n 1是有贡献的 所以我们只需求一个前缀和 即…

KYOCERA Programming Contest 2021(AtCoder Beginner Contest 200)

KYOCERA Programming Contest 2021&#xff08;AtCoder Beginner Contest 200&#xff09; A - CenturyB - 200th ABC-200C - Ringos Favorite Numbers 2D - Happy Birthday! 2E - Patisserie ABC 2 导读&#xff1a; 简单的题目&#xff0c;只说明题意&#xff0c;或者直接说明…

60道Linux面试题 ,让面试官无言以对

以下是Linux面试题目&#xff0c;答案一个个整理出来很麻烦&#xff0c;所以直接答案可以查看这里即可&#xff1a; http://www.yayihouse.com/yayishuwu/chapter/3629 1、Linux 软中断和工作队列的作用是什么?2、Linux 通过什么方式实现系统调用?3、linux如何唯一标识一个…

Hadoop 之 单机部署和测试(一)

Hadoop单机部署和测试 一.单机部署1.安装 JDK&#xff08;JDK11&#xff09;2.安装 HADOOP3.测试 一.单机部署 系统版本&#xff1a;cat /etc/anolis-release1.安装 JDK&#xff08;JDK11&#xff09; #!/bin/bashTOP_PATH$(pwd) JAVA_PATH/usr/local/java FILEls $TOP_PATH/…

Android 系统开发工具

Android 系统开发工具 1、SSH 服务与 Tabby Terminal1.1 配置 Ubuntu ssh 服务 2、Samba 服务器搭建3、Idegen Android Studio 查看源码3.1 修改android.iml文件 (可选) 4、AIdegen Android Studio 查看源码4.1 准备工作4.2 Android Studio 配置4.2.1 添加源码中的 jdk 和 sd…