# ZOJ Monthly, March 2018

A. Easy Number Game

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=100010;
int n,m,i,Case,a[N];long long ans;
int main(){
scanf("%d",&Case);
while(Case--){
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)scanf("%d",&a[i]);
sort(a+1,a+n+1);
ans=0;
for(i=1;i<=m;i++)ans+=1LL*a[i]*a[m*2+1-i];
printf("%lld\n",ans);
}
}


B. Lucky Man

$\sum_{i=1}^n\lfloor\frac{n}{n-i+1}\rfloor=\sum_{i=1}^n\lfloor\frac{n}{i}\rfloor=\sum_{i=1}^n d(i)$

C = int(raw_input())
for i in range(0, C):
n = int(raw_input())
if n < 2 :
print n
continue
m = 2
tmpn, len = n, 0
while tmpn > 0:
tmpn /= 10
len += 1
base, digit, cur = 300, len / m, len % m
while (cur + m <= base) and (digit > 0):
cur += m
digit -= 1
div = 10 ** (digit * m)
tmpn = n / div
x = int(float(tmpn) ** (1.0 / m))
x *= (10 ** digit)
while True:
x0 = x
x = x + x * (n - x ** m) / (n * m)
if x == x0: break
while (x + 1) ** m <= n:
x = x + 1
print x % 2


C. Travel along the Line

#include<cstdio>
const int N=1000010,P=1000000007;
int i,fac[N],inv[N],Case,n,m,x,y,z,ans,p[N];
inline int C(int n,int m){return n<m?0:1LL*fac[n]*inv[m]%P*inv[n-m]%P;}
int main(){
for(fac[0]=fac[1]=1,i=2;i<N;i++)fac[i]=1LL*fac[i-1]*i%P;
for(inv[0]=inv[1]=1,i=2;i<N;i++)inv[i]=1LL*(P-inv[P%i])*(P/i)%P;
for(i=2;i<N;i++)inv[i]=1LL*inv[i-1]*inv[i]%P;
for(p[0]=1,p[1]=inv[2],i=2;i<N;i++)p[i]=1LL*p[i-1]*p[1]%P;
scanf("%d",&Case);
while(Case--){
scanf("%d%d",&n,&m);
ans=0;
for(i=0;i<=n;i++){
x=i;//1
y=i-m;//-1
z=n-x-y;//0
if(y<0||y>n||z<0||z>n)continue;
ans=(1LL*C(n,x)*C(n-x,y)%P*p[(x+y)*2+z]+ans)%P;
}
printf("%d\n",ans);
}
}


D. Machine Learning on a Tree

#include<cstdio>
const int N=100010,inf=100000000;
inline void up(int&a,int b){a>b?(a=b):0;}
int Case,n,a[N],i,x,y,f[N][2],h[2],g[N],v[N<<1],nxt[N<<1],ed;
void dfs(int x,int y){
f[x][0]=f[x][1]=inf;
if(a[x]==0)f[x][0]=0;
else if(a[x]==1)f[x][1]=0;
else f[x][0]=f[x][1]=0;
for(int i=g[x];i;i=nxt[i]){
int u=v[i];
if(u==y)continue;
dfs(u,x);
for(int j=0;j<2;j++)h[j]=inf;
for(int j=0;j<2;j++)for(int k=0;k<2;k++)up(h[j],f[x][j]+f[u][k]+(j^k));
for(int j=0;j<2;j++)f[x][j]=h[j];
}
}
int main(){
scanf("%d",&Case);
while(Case--){
scanf("%d",&n);
for(i=1;i<=n;i++)scanf("%d",&a[i]);
for(ed=i=0;i<=n;i++)g[i]=0;
dfs(1,0);
up(f[1][0],f[1][1]);
printf("%d\n",f[1][0]);
}
}


E. Yet Another Tree Query Problem

$[l,r]$的连通块数量$=$点数$-$边数$=r-l+1-$两端点都在该区间内的树边数量。

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=200010;
int Case,n,m,i,x,y,ans[N],bit[N],ce;
struct E{int x,y,t;E(){}E(int _x,int _y,int _t){x=_x,y=_y,t=_t;}}e[N*3];
inline bool cmp(const E&a,const E&b){
if(a.x!=b.x)return a.x>b.x;
return a.t<b.t;
}
inline int ask(int x){int t=0;for(;x;x-=x&-x)t+=bit[x];return t;}
int main(){
scanf("%d",&Case);
while(Case--){
scanf("%d%d",&n,&m);
ce=0;
for(i=1;i<n;i++){
scanf("%d%d",&x,&y);
if(x>y)swap(x,y);
e[++ce]=E(x,y,0);
}
for(i=1;i<=m;i++){
scanf("%d%d",&x,&y);
ans[i]=y-x+1;
e[++ce]=E(x,y,i);
}
sort(e+1,e+ce+1,cmp);
for(i=1;i<=n;i++)bit[i]=0;
for(i=1;i<=m;i++)printf("%d\n",ans[i]);
}
}


F. And Another Data Structure Problem

#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
using namespace std;
const int N=100010,M=262150,P=99971;
int i,j,k,vis[N],f[N],q[N],m,mark[N];
int tot,cur,cnt,have[N],len[100],st[100],en[100],posx[N],posy[N];
int tag[M],val[M][72],ok[M][5],sum[M],ret[M];
int Case,n,qqq,op,x,y,a[N];
static int pool[1000];
tag[x]+=p;
int s=sum[x];
for(int i=0;i<cnt;i++)if(ok[x][i]){
int l=len[i],ST=st[i];
int t=p%l;
t=(l-t)%l;
if(!t)continue;
s-=val[x][ST];
if(s<0)s+=P;
int j;
memcpy(pool+t,val[x]+ST,(l-t)<<2);
memcpy(pool,val[x]+ST+l-t,t<<2);
memcpy(val[x]+ST,pool,l<<2);
//for(j=0;j+t<l;j++)pool[j+t]=val[x][ST+j];
//for(;j<l;j++)pool[j+t-l]=val[x][ST+j];
//for(j=0;j<l;j++)val[x][ST+j]=pool[j];
s+=val[x][ST];
if(s>=P)s-=P;
}
sum[x]=s;
}
inline void pb(int x){
if(tag[x]){
tag[x]=0;
}
}
inline void upd(int&a,int b){a=a+b<P?a+b:a+b-P;}
inline void up(int x){
sum[x]=(sum[x<<1]+sum[x<<1|1])%P;
ret[x]=ret[x<<1]+ret[x<<1|1];
for(int i=0;i<cnt;i++)ok[x][i]=ok[x<<1][i]+ok[x<<1|1][i];
if(!ret[x])for(int i=0;i<cur;i++){
val[x][i]=val[x<<1][i];
upd(val[x][i],val[x<<1|1][i]);
}
}
inline void init(int x,int y){
for(int i=0;i<cnt;i++)ok[x][i]=0;
sum[x]=y;
if(!mark[y]){
ret[x]=1;
}else{
ret[x]=0;
for(int i=0;i<cur;i++)val[x][i]=0;
int o=posx[y];
ok[x][o]=1;
for(int i=0;i<len[o];i++){
val[x][st[o]+i]=y;
y=f[y];
}
}
}
void build(int x,int a,int b){
tag[x]=0;
if(a==b){
init(x,::a[a]);
return;
}
int mid=(a+b)>>1;
build(x<<1,a,mid);
build(x<<1|1,mid+1,b);
up(x);
}
void change(int x,int a,int b,int c,int d){
if(c<=a&&b<=d){
if(!ret[x]){
return;
}
if(a==b){
init(x,::a[a]=f[::a[a]]);
return;
}
}
pb(x);
int mid=(a+b)>>1;
if(c<=mid)change(x<<1,a,mid,c,d);
if(d>mid)change(x<<1|1,mid+1,b,c,d);
up(x);
}
int ask(int x,int a,int b,int c,int d){
if(c<=a&&b<=d)return sum[x];
pb(x);
int mid=(a+b)>>1,t=0;
return t%P;
}
int main(){
for(i=0;i<P;i++)f[i]=1LL*i*i%P*i%P;
for(i=0;i<P;i++)have[i]=-1;
for(i=0;i<P;i++)if(!vis[i]){
for(j=i;!vis[j];j=f[j])vis[j]=1;
if(mark[j])continue;
q[m=1]=j;
for(k=f[j];k!=j;k=f[k])q[++m]=k;
for(j=1;j<=m;j++)mark[q[j]]=1;
if(have[m]==-1){
have[m]=cnt;
len[cnt]=m;
st[cnt]=cur;
en[cnt]=cur+m;
cur+=m;
//[st,en)
cnt++;
}
for(j=1;j<=m;j++)posx[q[j]]=have[m],posy[q[j]]=j-1;
}
scanf("%d",&Case);
//Case=1;
while(Case--){
scanf("%d%d",&n,&qqq);
//n=100000;
//qqq=100000;
for(i=1;i<=n;i++){
scanf("%d",&a[i]);
//a[i]=rand();
a[i]%=P;
}
build(1,1,n);
while(qqq--){
//op=rand()%2+1;
//x=rand()%n+1;
//y=rand()%n+1;
//if(x>y)swap(x,y);
scanf("%d%d%d",&op,&x,&y);
if(op==1)change(1,1,n,x,y);
}
}
}


G. Neighboring Characters

#include<cstdio>
#include<cstring>
typedef long long ll;
const int N=2000010,D=233,P=1000000009;
int C,n,m,i,j,k,len;char a[N],ans[N];ll pow[N],f[N];
int Case;
inline ll hash(int l,int r){return((f[r]-f[l-1]*pow[r-l+1])%P+P)%P;}
int main(){
for(pow[0]=i=1;i<N;i++)pow[i]=pow[i-1]*D%P;
scanf("%d",&Case);
while(Case--){
scanf("%s",a+1);
n=strlen(a+1);m=n+n;
for(i=1;i<=n;i++)a[i+n]=a[i];
for(i=1;i<=m;i++)f[i]=(f[i-1]*D+a[i])%P;
for(i=0;i<n;i++)ans[i]='0';
for(i=1;i<=m;i=j+1){
for(j=i;j<m&&a[j]!=a[j+1];j++);
len=j-i+1;
for(k=2;k<=len&&k<=n;k++)if(hash(i,i+len-k)!=hash(j-len+k,j))ans[n-k]='1';
}
for(i=0;i<n-1;i++)putchar(ans[i]);puts("1");
}
return 0;
}


H. Happy Sequence

$f[i][j]$表示长度为$i$的序列，最后一项为$j$的方案数，调和级数枚举$j$的倍数$k$转移给$f[i+1][k]$即可。

#include<cstdio>
const int N=2010,P=1000000007;
int Case,n,m,i,j,k,f[N][N],ans;
inline void up(int&a,int b){a=a+b<P?a+b:a+b-P;}
int main(){
scanf("%d",&Case);
while(Case--){
scanf("%d%d",&n,&m);//length m
for(i=0;i<=m;i++)for(j=1;j<=n;j++)f[i][j]=0;
for(i=1;i<=n;i++)f[1][i]=1;
for(i=1;i<m;i++)for(j=1;j<=n;j++)for(k=j;k<=n;k+=j)up(f[i+1][k],f[i][j]);
ans=0;
for(i=1;i<=n;i++)up(ans,f[m][i]);
printf("%d\n",ans);
}
}


I. Your Bridge is under Attack

#include<cstdio>
#include<algorithm>
const int N=100010;
using namespace std;
typedef long long ll;
int Case,n,m,i,root,cmp_d,ans,A,B;
ll LB,LA,LC;
struct node{
int d[2];
int l,r;
int Max[2],Min[2];
int sum;
}t[N];
inline bool cmp(const node&a,const node&b){
return a.d[cmp_d]<b.d[cmp_d];
}
inline void umax(int&a,int b){if(a<b)a=b;}
inline void umin(int&a,int b){if(a>b)a=b;}
inline void up(int x){
if(t[x].l){
umax(t[x].Max[0],t[t[x].l].Max[0]);
umin(t[x].Min[0],t[t[x].l].Min[0]);
umax(t[x].Max[1],t[t[x].l].Max[1]);
umin(t[x].Min[1],t[t[x].l].Min[1]);
}
if(t[x].r){
umax(t[x].Max[0],t[t[x].r].Max[0]);
umin(t[x].Min[0],t[t[x].r].Min[0]);
umax(t[x].Max[1],t[t[x].r].Max[1]);
umin(t[x].Min[1],t[t[x].r].Min[1]);
}
}
int build(int l,int r,int D){
int mid=(l+r)>>1;
cmp_d=D;
nth_element(t+l+1,t+mid+1,t+r+1,cmp);
t[mid].Max[0]=t[mid].Min[0]=t[mid].d[0];
t[mid].Max[1]=t[mid].Min[1]=t[mid].d[1];
t[mid].sum=1;
if(l!=mid)t[mid].l=build(l,mid-1,!D);else t[mid].l=0;
if(r!=mid)t[mid].r=build(mid+1,r,!D);else t[mid].r=0;
up(mid);
return mid;
}
inline bool check(int xl,int xr,int yl,int yr){
ll t=-LB*xl+LC;
if(LA*yl<=t&&t<=LA*yr)return 1;
t=-LB*xr+LC;
if(LA*yl<=t&&t<=LA*yr)return 1;
t=-LA*yl+LC;
if(LB*xl<=t&&t<=LB*xr)return 1;
t=-LA*yr+LC;
if(LB*xl<=t&&t<=LB*xr)return 1;
return 0;
}
if(!check(t[x].Min[0],t[x].Max[0],t[x].Min[1],t[x].Max[1]))return;
if(LB*t[x].d[0]+LA*t[x].d[1]==LC)ans++;
}
int main(){
scanf("%d",&Case);
while(Case--){
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)scanf("%d%d",&t[i].d[0],&t[i].d[1]);
root=build(1,n,0);
while(m--){
scanf("%d%d",&A,&B);
LA=A;
LB=B;
LC=LA*LB;
ans=0;
printf("%d\n",ans);
}
}
}


J. Super Brain

#include<cstdio>
const int N=1000010;
int Case,n,i,a[N],b[N],f[N],g[N],ans;
int main(){
scanf("%d",&Case);
while(Case--){
scanf("%d",&n);
for(i=1;i<=n;i++)scanf("%d",&a[i]),f[a[i]]=g[a[i]]=0;
for(i=1;i<=n;i++)scanf("%d",&b[i]),f[b[i]]=g[b[i]]=0;
for(i=1;i<=n;i++)f[a[i]]++;
for(i=1;i<=n;i++)g[b[i]]++;
for(i=1;i<=n;i++)if(f[a[i]]==1&&g[a[i]]==1)ans=a[i];
for(i=1;i<=n;i++)if(f[b[i]]==1&&g[b[i]]==1)ans=b[i];
printf("%d\n",ans);
}
}


posted @ 2018-03-10 18:40 Claris 阅读(...) 评论(...) 编辑 收藏