博客园 首页 私信博主 显示目录 隐藏目录 管理 动画

AtCoder Regular Contest 075

任意门

C - Bugged

题意:类似装箱问题,但是最后体积总和不能为10的倍数。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define MN 30001
using namespace std;
 
int read_p,read_ca;
inline int read(){
    read_p=0;read_ca=getchar();
    while(read_ca<'0'||read_ca>'9') read_ca=getchar();
    while(read_ca>='0'&&read_ca<='9') read_p=read_p*10+read_ca-48,read_ca=getchar();
    return read_p;
}
const int MOD=1e9+7;
int n,a[11000],w;
int main(){
    int i,j,k;
    n=read();
    a[0]=1;
    while(n--){
        w=read();
        for (i=10000;i>=0;i--) a[i+w]|=a[i];
    }
    for (i=10000;i>=0;i--) if (a[i]&&i%10) return printf("%d\n",i),0;
    puts("0");
}
View Code

 

D - Widespread

题意:n只怪物,每只有一个生命值,每次攻击可以指定一只造成A点伤害,其他所有造成B点伤害(A>B),问全部消灭的最小攻击次数。

题解:二分攻击次数。

#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define MN 300001
#define int long long
using namespace std;
 
int read_p,read_ca;
inline int read(){
    read_p=0;read_ca=getchar();
    while(read_ca<'0'||read_ca>'9') read_ca=getchar();
    while(read_ca>='0'&&read_ca<='9') read_p=read_p*10+read_ca-48,read_ca=getchar();
    return read_p;
}
const int MOD=1e9+7;
int n,a[110000],w=0,mmh=0,A,B,L=0,R=1e9;
inline bool ju(int x){
    int u=B*x,s=0;
    for (int i=1;i<=n;i++)
    if (a[i]>u) s+=(a[i]-u+A-1)/A;
    return s<=x;
}
signed main(){
    int i,j,k;
    n=read();A=read();B=read();A-=B;
    for (i=1;i<=n;i++) a[i]=read();
    while (L<R){
        int mid=L+R>>1;
        if (ju(mid)) R=mid;else L=mid+1;
    }
    printf("%lld\n",L);
}
View Code

 

E - Meaningful Mean

题意:求一个数组中,平均值不小于k的连续子序列个数。

题解:全部减k之后数据结构处理前缀和即可。

#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define MN 210001
#define int long long
using namespace std;
 
int read_p,read_ca;
inline int read(){
    read_p=0;read_ca=getchar();
    while(read_ca<'0'||read_ca>'9') read_ca=getchar();
    while(read_ca>='0'&&read_ca<='9') read_p=read_p*10+read_ca-48,read_ca=getchar();
    return read_p;
}
const int MOD=1e9+7,M=1e15;
int n,a[MN],ro=0,mmh=0,k,ls[MN*30],rs[MN*30],s[MN*30],NUM=0;
void add(int &p,int l,int r,int k){
    if (!p) p=++NUM,ls[p]=rs[p]=s[p]=0;
    s[p]++;
    if (l==r) return; 
    int mid=l+r>>1;
    if (k<=mid) add(ls[p],l,mid,k);else add(rs[p],mid+1,r,k);
}
int ask(int p,int l,int r,int k){
    if (!p) return 0;
    if (r<=k) return s[p];
    
    int mid=l+r>>1;
    if (k<=mid) return ask(ls[p],l,mid,k);else return ask(rs[p],mid+1,r,k)+ask(ls[p],l,mid,k);
}
signed main(){
    int i,j,k;
    n=read();k=read();
    add(ro,-M,M,0);
    for (i=1;i<=n;i++){
        a[i]=read()-k;a[i]+=a[i-1];
        mmh+=ask(ro,-M,M,a[i]);
        add(ro,-M,M,a[i]);
    }
    printf("%lld\n",mmh);
}
View Code

 

F - Mirrored

题意:记rev(N)为把N在10进制下翻转以后的值(无前导0),给出D,求rev(N)=N+D的N的数量。

题解:好开心在考场上搞了出来。其实就是个暴力。枚举N的位数d,再同时枚举第i和d+1-i位,这样可以确定差中第i位和第d+1-i位的可能值,从而实现剪枝。然后你会发现这玩意可以记忆化……

#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define MN 21001
#define int long long
using namespace std;
 
int read_p,read_ca;
inline int read(){
    read_p=0;read_ca=getchar();
    while(read_ca<'0'||read_ca>'9') read_ca=getchar();
    while(read_ca>='0'&&read_ca<='9') read_p=read_p*10+read_ca-48,read_ca=getchar();
    return read_p;
}
const int MOD=1e9+7;
int n,a[MN],B[MN],x,mmh=0,mm[20][20][2][2];
inline int M(int x){return x<0?x+10:x;}
inline void work(int p,int n,int a,int b){
    if (mm[p][n][a][b]!=-1) {mmh+=mm[p][n][a][b];return;}
    int u=mmh;
    if (p+p-1==n){
        if (a==0&&b==0) mmh+=10*(B[p]==0);else
        if (a==1&&b==1) mmh+=10*(B[p]==9);
        return;
    }
    if (p+p-1>n){
        mmh+=a==b;
        return;
    }
    for (int i=p==1;i<=9;i++)
    for (int j=0;j<=9;j++)
    if (M(i-j-b)==B[p]&&(a==(j<i)||j==i)&&(M(j-i)==B[n+1-p]||M(j-1-i)==B[n+1-p])){
        if (a){
            if (j==i&&B[n+1-p]==0) continue;
            work(p+1,n,M(j-1-i)==B[n+1-p],i-b-j<0);
        }else{
            if (j==i&&B[n+1-p]==9) continue;
            work(p+1,n,M(j-1-i)==B[n+1-p],i-b-j<0);
        }
    }
    mm[p][n][a][b]=mmh-u;
}
signed main(){
    int i,j,k;
    x=n=read();
    if (n%9) return puts("0"),0;
    for (k=1;k<=10&&x;k++) B[k]=x%10,x/=10;k--;
    for (int i=k;i<=18;i++) memset(mm,-1,sizeof(mm)),work(1,i,0,0);
    printf("%lld\n",mmh);
}
View Code

涨rating啦好开心

posted @ 2017-06-03 21:59  swm_sxt  阅读(225)  评论(1编辑  收藏  举报