传送门

当我打开比赛界面的时候所有题目都已经被一血了……

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

颓柿子

\[\begin{aligned}
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\)做法……一看数据范围就是点名被卡的……

然后翻了翻具体数学,得知

\[\begin{aligned}
& 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 题解的更多相关文章

  1. CodeChef November Challenge 2019 Division 1题解

    传送门 AFO前的最后一场CC了--好好打吧-- \(SIMGAM\) 偶数行的必定两人平分,所以只要抢奇数行中间那个就行了 这题怎么被爆破了 //quming #include<bits/st ...

  2. Codechef July Challenge 2019 Division 1题解

    题面 \(CIRMERGE\) 破环成链搞个裸的区间\(dp\)就行了 //quming #include<bits/stdc++.h> #define R register #defin ...

  3. 【CodeChef】December Challenge 2019 Div1 解题报告

    点此进入比赛 这次比赛本来想好好打的,但不幸的是,这周先是要认真复习准备月考,考完又是发烧在床上躺了一个周末,所以最终没能打完. 我还是好弱啊. \(T1\):Binary XOR(点此看题面) 大致 ...

  4. Codechef November Challenge 2019 Division 1

    Preface 这场CC好难的说,后面的都不会做QAQ 还因为不会三进制位运算卷积被曲明姐姐欺负了,我真是太菜了QAQ PS:最后还是狗上了六星的说,期待两(三)场之内可以上七星 Physical E ...

  5. Codechef October Challenge 2019 Division 1

    Preface 这次CC难度较上两场升高了许多,后面两题都只能借着曲明姐姐和jz姐姐的仙气来做 值得一提的是原来的F大概需要大力分类讨论,结果我写了一大半题目就因为原题被ban了233 最后勉强涨了近 ...

  6. Codechef September Challenge 2019 Division 2

    Preface 这确实应该是我打过的比较水的CC了(其实就打过两场) 但由于我太弱了打的都是Div2,所以会认为上一场更简单,其实上一场Div的数据结构是真的毒 好了废话不多说快速地讲一下 A Eas ...

  7. Codechef August Challenge 2019 Division 2

    Preface 老年菜鸡终于开始打CC了,由于他太弱了所以只能打Div2 因为台风的原因challenge并没有写,所以水了个Rank7 A Football SB模拟题不解释 #include< ...

  8. Codechef April Challenge 2019 Division 2

    Maximum Remaining 题意:给n个数,取出两个数$a_{i}$,$a_{j}$,求$a_{i}\% a_{j}$取模的最大值 直接排个序,第二大(严格的第二大)模第一大就是答案了. #i ...

  9. May Challenge 2019 Division 2 水题讲解

    Reduce to One 这题其实蛮水的? 题意就是说: 给定一个 1~n 的序列,每次挑两个数 x y 合并,合并值为 \(x+y+xy\) ,然后求不断合并最后剩下的一个的最大值 随便搞搞发现答 ...

随机推荐

  1. 当Windows操作系统关机时,不会执行Windows Service的OnStop方法(转载)

    Windows Service OnStop when computer shutdown 问: I'm writing a Windows Service in C#. I want to take ...

  2. 树莓派安装window ioT

    下载安装器 https://developer.microsoft.com/zh-cn/windows/iot/Downloads 操作设备

  3. Java IO---字节流和字符流

    一.IO流简介 流 流是一个抽象概念,Java程序和外部设备(可以是硬盘上的文件,也可以是网络设备)之间的输入输出操作是基于流的. 流就好比水管中的水流,具有流入和流出,类比数据的输入和输出. Jav ...

  4. Django--一对多表操作

    目录 Django--一对多表操作 需求 步骤 添加路由映射关系 学生表的增删改查 ajax更新和添加 Django--一对多表操作 今天还以一个学生管理系统为例,先通过pymysql这个模块,进行一 ...

  5. 如何快速找到Chrome配置文件路径,MAC 与window 都适用

    Chrome 的配置文件主要用于存储浏览器的相关配置.书签.扩展插件和密码等,Chrome 配置文件会存储在用户计算机的一个单独文件夹当中,当你升级或重装浏览器时,这些已有配置将可以被完整保存下来. ...

  6. Js中级复习

    JS中级复习—— 1,this   就是js的关键字 用途:指向某一个对象 如何判断this指向: 函数(方法)内—— 一种以函数的方式调用(不带.)this指向window 一种以方法的形式调用(函 ...

  7. 关于UDP协议

    UDP协议的特点. 1.UDP是一个无连接协议,传输数据之前接收端和发送端之间不建立连接. 想传输数据的时候就抓取数据扔出去,不监控是否被正确和全面的接受到. 2.因为不需要建立连接,也就不需要维护连 ...

  8. FreeRTOS 任务通知模拟消息邮箱

    举例 void task1_task(void *pvParameters) { u8 key; BaseType_t err; while(1) { key=KEY_Scan(0); //扫描按键 ...

  9. 99.9%的Java程序员都说不清的问题:JVM中的对象内存布局?

    本文转载自公众号:石彬的架构笔记,阅读大约需要8分钟. 作者:李瑞杰 目前就职于阿里巴巴,资深 JVM 研究人员 在 Java 程序中,我们拥有多种新建对象的方式.除了最为常见的 new 语句之外,我 ...

  10. 文章中左下角的妹子live2d看板娘

    关键词: live2d看板娘 自行搜索即可 攻略很多