December Challenge 2019 Division 1 题解
当我打开比赛界面的时候所有题目都已经被一血了……
BINXOR
直接把异或之后二进制最多和最少能有多少个\(1\)算出来,在这个范围内枚举,组合数算一下就行了。注意\(1\)的个数是\(2\)个\(2\)个变的
//quming
#include<bits/stdc++.h>
#define R register
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
const int P=1e9+7;
inline void upd(R int &x,R int y){(x+=y)>=P?x-=P:0;}
inline int inc(R int x,R int y){return x+y>=P?x+y-P:x+y;}
inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
int ksm(R int x,R int y){
R int res=1;
for(;y;y>>=1,x=mul(x,x))(y&1)?res=mul(res,x):0;
return res;
}
const int N=2e5+5;
char s[N];int cnt[2][2],fac[N],ifac[N],n,T,res,l,r;
inline void init(int n=2e5){
fac[0]=ifac[0]=1;fp(i,1,n)fac[i]=mul(fac[i-1],i);
ifac[n]=ksm(fac[n],P-2);fd(i,n-1,1)ifac[i]=mul(ifac[i+1],i+1);
}
inline int C(R int n,R int m){return m<0||m>n?0:1ll*fac[n]*ifac[m]%P*ifac[n-m]%P;}
int main(){
// freopen("testdata.in","r",stdin);
init();
for(scanf("%d",&T);T;--T){
scanf("%d",&n),cnt[0][0]=cnt[0][1]=cnt[1][0]=cnt[1][1]=0;
scanf("%s",s+1);fp(i,1,n)++cnt[0][s[i]-'0'];
scanf("%s",s+1);fp(i,1,n)++cnt[1][s[i]-'0'];
l=n-min(cnt[0][0],cnt[1][0])-min(cnt[0][1],cnt[1][1]);
r=min(cnt[0][0],cnt[1][1])+min(cnt[1][0],cnt[0][1]);
// printf("%d %d\n",l,r);
assert((r-l)&1^1);
res=0;
for(R int i=l;i<=r;i+=2)upd(res,C(n,i));
printf("%d\n",res);
}
return 0;
}
CHFRAN
把首先原问题肯定是找某个分界线,然后左边一组右边一组最优,所以我们把所有线段转成\([l,r-1]\),然后可以转化为对于某个点只要它没有被覆盖且左右都有线段即合法,那么我们枚举这个点,把所有跨过它的线段全部删掉就行了
//quming
#include<bits/stdc++.h>
#define R register
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
const int N=5e5+5;
int b[N],c[N],sf[N],fs[N],l[N],r[N],n,T,tot,res;
int main(){
// freopen("testdata.in","r",stdin);
for(scanf("%d",&T);T;--T){
scanf("%d",&n),res=n+1,tot=0;
fp(i,1,n){
scanf("%d%d",&l[i],&r[i]),--r[i];
b[++tot]=l[i],b[++tot]=r[i],b[++tot]=l[i]-1,b[++tot]=r[i]+1;
}
sort(b+1,b+1+tot),tot=unique(b+1,b+1+tot)-b-1;
fp(i,0,tot+1)c[i]=sf[i]=fs[i]=0;
fp(i,1,n){
l[i]=lower_bound(b+1,b+1+tot,l[i])-b;
r[i]=lower_bound(b+1,b+1+tot,r[i])-b;
++c[l[i]],--c[r[i]+1],++sf[r[i]],++fs[l[i]];
}
fp(i,1,tot+1)c[i]+=c[i-1],sf[i]+=sf[i-1];
fd(i,tot,0)fs[i]+=fs[i+1];
fp(i,1,tot)if(c[i]<n-1&&sf[i-1]>0&&fs[i+1]>0)cmin(res,c[i]);
printf("%d\n",res==n+1?-1:res);
}
return 0;
}
BINADD
首先特判掉\(B=0\)的情况,然后打个表发现答案就是\(A+B\)二进制时最长连续进位个数\(+1\)(比方说A的第\(0\)位和\(B\)的第\(0\)位都是\(1\),且从\(1\)到\(k\)位\(A\)和\(B\)恰好有一个为\(1\),那么\(A+B\)的时候这里就会连续进位\(k+1\)次)
发现规律之后证明就是显然的了,因为它实现的二进制加法就是每次把会进位的那些提出来单独处理,那么最多只会做最长连续进位个数次了
//quming
#include<bits/stdc++.h>
#define R register
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
const int N=1e5+5;
char s[N],t[N];int n,m,lim,res,cnt,T;
inline int max(R int x,R int y){return x>y?x:y;}
int main(){
// freopen("testdata.in","r",stdin);
for(scanf("%d",&T);T;--T){
scanf("%s%s",s+1,t+1),n=strlen(s+1),m=strlen(t+1),lim=max(n,m);
if(m==1&&t[m]=='0'){puts("0");continue;}
reverse(s+1,s+1+n),reverse(t+1,t+1+m);
fp(i,1,n)s[i]-='0';fp(i,n+1,lim)s[i]=0;
fp(i,1,m)t[i]-='0';fp(i,m+1,lim)t[i]=0;
res=0;
fp(i,1,lim)if(s[i]&t[i]){
cnt=1,++i;
while(i<=lim&&(s[i]^t[i]))++i,++cnt;
--i,cmax(res,cnt);
}
printf("%d\n",res+1);
}
return 0;
}
STICNOT
贪心都不会,被学弟鄙视了
首先我们发现,点和边随便乱放,而且一个点的权值一定要大于等于它连接的所有边权的最大值
那么我们把边从大到小往里加入,加入的第一条边连接的两个点,点权的下界就已经确定了(以为不可能有别的边比第一条边边权更大),加入第二条边的时候,容易发现肯定是与这两个点其中的某一个相连是最优的(因为这样可以只确定一个点的下界,另一个点的下界之后才被确定,而后确定的下界一定比先确定的下界要小)。那么相当于除了第一条边需要两个点之外,其余每条边都需要一个大于等于它权值的点,直接贪心即可,树的形态都不用管
//quming
#include<bits/stdc++.h>
#define R register
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
const int N=1e5+5;
int a[N],b[N],n,res,T;
int calc(){
for(R int i=1,j=1;i<=n;++i){
while(j<=n&&a[j]<b[i])++j;
if(j>n)return n-i+1;
++j;
}
return 0;
}
int main(){
// freopen("testdata.in","r",stdin);
for(scanf("%d",&T);T;--T){
scanf("%d",&n);
for(R int i=1,u,v;i<n;++i)scanf("%d%d%d",&u,&v,&b[i]);
fp(i,1,n)scanf("%d",&a[i]);
sort(b+1,b+n),b[n]=b[n-1];
sort(a+1,a+1+n);
printf("%d\n",calc());
}
return 0;
}
BINOFEV
颓柿子
S
&=\sum_{i=0}^n{p\choose r}\\
&={1\over r!}\sum_{i=0}^n \left(p^i\right)^{\underline r}
\end{aligned}
\]
所以如果我们能把\(x^{\underline r}\)转成普通多项式,那么对于\(x^i\)那一项,前面系数相等,后面对于所有的\(p^j\)来说是一个等比数列求和,那么就可以计算了
然而我只会\(O(n\log^2 n)\)的分治\(NTT\)做法……一看数据范围就是点名被卡的……
然后翻了翻具体数学,得知
& x^{\underline n}=\sum_k\begin{bmatrix}{n\\ k}\end{bmatrix}(-1)^{n-k}x^{k}\\
\end{aligned}
\]
又翻了翻洛谷,发现第一类斯特林数的行可以\(O(n\log n)\)求 这里
然后这题就做完了
//quming
#include<bits/stdc++.h>
#define R register
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
const int P=998244353;
inline void upd(R int &x,R int y){(x+=y)>=P?x-=P:0;}
inline int inc(R int x,R int y){return x+y>=P?x+y-P:x+y;}
inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
int ksm(R int x,R int y){
R int res=1;
for(;y;y>>=1,x=mul(x,x))(y&1)?res=mul(res,x):0;
return res;
}
int kkk(R int x,R int y){
R int res=1,d=1;
for(;y;y>>=1,d=mul(d,x+1),x=mul(x,x))if(y&1)res=inc(mul(res,x),d);
return res;
}
const int N=(1<<20)+5;
int fac[N],ifac[N],lg[N],r[25][N],up[N],rt[2][N],inv[25];
int lim,d;
inline void swap(R int &x,R int &y){R int t=x;x=y,y=t;}
inline int C(R int n,R int m){return m>n?0:1ll*fac[n]*ifac[m]%P*ifac[n-m]%P;}
void init(){
fac[0]=ifac[0]=1;fp(i,1,1048576)fac[i]=mul(fac[i-1],i);
ifac[1048576]=ksm(fac[1048576],P-2);fd(i,1048575,1)ifac[i]=mul(ifac[i+1],i+1);
fp(d,1,20){
fp(i,1,(1<<d)-1)r[d][i]=(r[d][i>>1]>>1)|((i&1)<<(d-1));
inv[d]=ksm(1<<d,P-2),lg[1<<d]=d;
fp(i,1<<(d-1),(1<<d)-1)up[i]=(1<<d);
}
for(R int t=(P-1)>>1,i=1,x,y;i<1048576;i<<=1,t>>=1){
x=ksm(3,t),y=ksm(332748118,t),rt[0][i]=rt[1][i]=1;
fp(k,1,i-1)
rt[1][i+k]=mul(rt[1][i+k-1],x),
rt[0][i+k]=mul(rt[0][i+k-1],y);
}
}
void NTT(int *A,int ty){
fp(i,0,lim-1)if(i<r[d][i])swap(A[i],A[r[d][i]]);
R int t;
for(R int mid=1;mid<lim;mid<<=1)
for(R int j=0;j<lim;j+=(mid<<1))
fp(k,0,mid-1)
A[j+k+mid]=dec(A[j+k],t=mul(rt[ty][mid+k],A[j+k+mid])),
A[j+k]=inc(A[j+k],t);
if(!ty){
t=inv[d];
fp(i,0,lim-1)A[i]=mul(A[i],t);
}
}
int f[N],n,T,m,p,res;
void solve(int *b,int len){
if(!len)return b[0]=1,void();
solve(b,len>>1);
lim=up[len],d=lg[lim];
int dm=(len>>1);
static int A[N],B[N];
for(R int i=0,c=1;i<=dm;++i,c=mul(c,dm))A[i]=mul(c,ifac[i]);
fp(i,0,dm)B[dm-i]=mul(b[i],fac[i]);
fp(i,dm+1,lim-1)A[i]=B[i]=0;
NTT(A,1),NTT(B,1);
fp(i,0,lim-1)A[i]=mul(A[i],B[i]);
NTT(A,0);
reverse(A,A+dm+1);
fp(i,0,dm)A[i]=mul(A[i],ifac[i]);fp(i,dm+1,lim-1)A[i]=0;
fp(i,0,dm)B[i]=b[i];fp(i,dm+1,lim-1)B[i]=0;
NTT(A,1),NTT(B,1);
fp(i,0,lim-1)A[i]=mul(A[i],B[i]);
NTT(A,0);
fp(i,0,len)b[i]=A[i];
if(len&1){
fd(i,len,1)b[i]=inc(mul(b[i],len-1),b[i-1]);
b[0]=mul(b[0],len-1);
}
}
int main(){
// freopen("testdata.in","r",stdin);
init();
for(scanf("%d",&T);T;--T){
scanf("%d%d%d",&n,&p,&m);
fp(i,0,m)f[i]=0;
solve(f,m);
res=0;
for(R int i=0,c=1;i<=m;++i,c=mul(c,p)){
R int ret=mul(f[i],kkk(c,n));
upd(res,(m-i)&1?P-ret:ret);
}
printf("%d\n",mul(res,ifac[m]));
}
return 0;
}
APAIRS
居然被一道sb题卡了这么久……
首先,计算\(score(i,j)\)的话,肯定是把两个数的十进制每一位从小到大排序,然后依次配对,这样一定是最优的,证明随便证
然后我们发现位与位之间的贡献是独立的,我们可以设\(f_{i,j}\)表示从小到大第\(i\)位为\(j\)的方案数,然后每次用\(f_{i,j}\)和\(f_{i,k}\)更新答案就行了
然后关于计算\(f_{i,j}\),我们可以直接枚举\(j\)的个数,以及小于\(j\)的个数,直接\(dp\)就行了,具体可以看代码
//quming
#include<bits/stdc++.h>
#define R register
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
const int P=1e9+7;
inline void upd(R int &x,R int y){(x+=y)>=P?x-=P:0;}
inline int inc(R int x,R int y){return x+y>=P?x+y-P:x+y;}
inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
int ksm(R int x,R int y){
R int res=1;
for(;y;y>>=1,x=mul(x,x))(y&1)?res=mul(res,x):0;
return res;
}
typedef long long ll;
ll l,r;int f[25][25],as[25][25],fac[25],ifac[25],inv[25];
int nd[25],sg[25],cnt[5],K,T,res;
void init(int n=20){
fac[0]=ifac[0]=fac[1]=ifac[1]=inv[0]=inv[1]=1;
fp(i,2,n){
fac[i]=mul(fac[i-1],i);
inv[i]=mul(P-P/i,inv[P%i]);
ifac[i]=mul(ifac[i-1],inv[i]);
}
fp(i,0,9)fp(j,0,9)as[i][j]=abs(i-j);
}
inline int calc(R int a,R int b,R int c){
return 1ll*fac[a+b+c]*ifac[a]%P*ifac[b]%P*ifac[c]%P*ksm(K,a)%P*ksm(9-K,c)%P;
}
void solve(int a,int b,int c,int op){
if(K==0&&a||K==9&&c)return;
cnt[0]=a,cnt[1]=b,cnt[2]=c;
R int res=0;
fd(i,20,1){
fp(j,0,nd[i]-1)if(cnt[sg[j]]){
--cnt[sg[j]];
upd(res,calc(cnt[0],cnt[1],cnt[2]));
++cnt[sg[j]];
}
if(!cnt[sg[nd[i]]])break;
--cnt[sg[nd[i]]];
if(i==1)++res;
}
if(op==-1)res=inc(0,P-res);
fp(i,a+1,a+b)upd(f[i][K],res);
}
int main(){
// freopen("testdata.in","r",stdin);
init();
for(scanf("%d",&T);T;--T){
scanf("%lld%lld",&l,&r),--l;
res=0,memset(f,0,sizeof(f));
fp(i,1,20)nd[i]=r%10,r/=10;
fp(k,0,9){
fp(i,0,k-1)sg[i]=0;fp(i,k+1,9)sg[i]=2;
sg[k]=1,K=k;
fp(i,0,19)fp(j,0,19-i)solve(i,20-i-j,j,1);
}
fp(i,1,20)nd[i]=l%10,l/=10;
fp(k,0,9){
fp(i,0,k-1)sg[i]=0;fp(i,k+1,9)sg[i]=2;
sg[k]=1,K=k;
fp(i,0,19)fp(j,0,19-i)solve(i,20-i-j,j,-1);
}
fp(i,1,20)fp(j,0,9)if(f[i][j])fp(k,j+1,9)if(f[i][k])
upd(res,2ll*f[i][j]*f[i][k]%P*as[j][k]%P);
printf("%d\n",res);
}
return 0;
}
December Challenge 2019 Division 1 题解的更多相关文章
- CodeChef November Challenge 2019 Division 1题解
传送门 AFO前的最后一场CC了--好好打吧-- \(SIMGAM\) 偶数行的必定两人平分,所以只要抢奇数行中间那个就行了 这题怎么被爆破了 //quming #include<bits/st ...
- Codechef July Challenge 2019 Division 1题解
题面 \(CIRMERGE\) 破环成链搞个裸的区间\(dp\)就行了 //quming #include<bits/stdc++.h> #define R register #defin ...
- 【CodeChef】December Challenge 2019 Div1 解题报告
点此进入比赛 这次比赛本来想好好打的,但不幸的是,这周先是要认真复习准备月考,考完又是发烧在床上躺了一个周末,所以最终没能打完. 我还是好弱啊. \(T1\):Binary XOR(点此看题面) 大致 ...
- Codechef November Challenge 2019 Division 1
Preface 这场CC好难的说,后面的都不会做QAQ 还因为不会三进制位运算卷积被曲明姐姐欺负了,我真是太菜了QAQ PS:最后还是狗上了六星的说,期待两(三)场之内可以上七星 Physical E ...
- Codechef October Challenge 2019 Division 1
Preface 这次CC难度较上两场升高了许多,后面两题都只能借着曲明姐姐和jz姐姐的仙气来做 值得一提的是原来的F大概需要大力分类讨论,结果我写了一大半题目就因为原题被ban了233 最后勉强涨了近 ...
- Codechef September Challenge 2019 Division 2
Preface 这确实应该是我打过的比较水的CC了(其实就打过两场) 但由于我太弱了打的都是Div2,所以会认为上一场更简单,其实上一场Div的数据结构是真的毒 好了废话不多说快速地讲一下 A Eas ...
- Codechef August Challenge 2019 Division 2
Preface 老年菜鸡终于开始打CC了,由于他太弱了所以只能打Div2 因为台风的原因challenge并没有写,所以水了个Rank7 A Football SB模拟题不解释 #include< ...
- Codechef April Challenge 2019 Division 2
Maximum Remaining 题意:给n个数,取出两个数$a_{i}$,$a_{j}$,求$a_{i}\% a_{j}$取模的最大值 直接排个序,第二大(严格的第二大)模第一大就是答案了. #i ...
- May Challenge 2019 Division 2 水题讲解
Reduce to One 这题其实蛮水的? 题意就是说: 给定一个 1~n 的序列,每次挑两个数 x y 合并,合并值为 \(x+y+xy\) ,然后求不断合并最后剩下的一个的最大值 随便搞搞发现答 ...
随机推荐
- [Leetcode] 1120. Maximum Average Subtree
Given the root of a binary tree, find the maximum average value of any subtree of that tree. (A subt ...
- 玩转zynq7010+ FPGA点亮三色灯
前期主要以开发Z-TURN的PL部分为主,以期望了解该芯片的逻辑架构和系统总线,以及所有外设,后面在开始PS部分的开发,闲话少说,先看整个7z010的系统框图,所有开发目前基于ISE14.6来设置, ...
- js两个不同类型值比较Boolean(0=='')
写js遇到的问题 本以为 Boolean(0=='') 结果为true 可是在控制台执行 Boolean(0==' ')trueBoolean(0==null)false 百度得知,两个不同类型值比较 ...
- mongo数据库的一些命令(对于新同学,按照我的步骤连一遍即可)
进入mongo mongo 查看数据库 show dbs;/show databases(); 第一个命令简单(admin和local数据库是系统自带的) 进入/创建数据库 use 数据库名字(如果有 ...
- Django 配置mysql遇到问题(一)
问题一: django.core.exceptions.ImproperlyConfigured: mysqlclient 1.3.13 or newer is required; you have ...
- Oracle数据库中 =:和 :=
=:应该相当于 a = :b 表明b是个绑定变量,需要执行时进行变量绑定. 变量绑定:变量绑定是指在sql语句的条件中使用变量而不是常量.比如shared pool里有两条sql语句,select * ...
- postgresql基于备份点PITR恢复
实验目的: 01.基于备份点直接恢复数据库 02.基于备份点后续增量wal日志恢复到特定的时间点 实验环境: centos7 postgresql9.5 01.安装postgresql9.5 post ...
- IDEA 创建类是自动添加注释和创建方法时快速添加注释
1.创建类是自动添加注释 /*** @Author: chiyl* @DateTime: ${DATE} ${TIME}* @Description: TODO*/2. 创建方法时快速添加注释2.1 ...
- initState 必须调用 super.initState(); 否则报错
@override void initState() { // initState 必须调用 super.initState(); 否则报错:info: This method overrides a ...
- el-tabs 使用
el-tabs 使用 文章标题 网址 https://www.cnblogs.com/yuxiaole/p/9523735.html https://www.jianshu.com/p/571d832 ...