部分刷题记录

1 篇文章 0 订阅
1 篇文章 0 订阅

BZOJ

BZOJ出新题了,赶紧去抢一血。没有数据?!Python 2B!
![这里写图片描述](https://img-blog.csdn.net/20170921205449546?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzYzNjgwOTE=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
重测后 

5018: [Snoi2017]英雄联盟

DP,用f[i][j]表示DP到第i个物品,花费为j时最大的方案数。
#include<cstdio>
#include<algorithm>
using namespace std;
#define ll long long
inline char tc(void){
    static char fl[10000],*A=fl,*B=fl;
    return A==B&&(B=(A=fl)+fread(fl,1,10000,stdin),A==B)?EOF:*A++;
}
inline ll read(void){
    ll a=0;static char c;
    while((c=tc())<'0'||c>'9');
    while(c>='0'&&c<='9')a=a*10+c-'0',c=tc();
    return a;
}
ll m;
int mx,n,k[122],c[122],ans=2e9;
ll dp[122][242781];
int main(void){
    register int i,j,l,x;
    n=read(),m=read();
    for(i=1;i<=n;++i)k[i]=read();
    for(i=1;i<=n;mx+=k[i]*c[i],++i)c[i]=read();
    dp[0][0]=1;
    for(i=1;i<=n;++i)
        for(j=0,x=0;j<=k[i];++j,x+=c[i]) 
            for(l=x;l<=mx;++l){
                dp[i][l]=max(dp[i][l],dp[i-1][l-x]*((j==0)?1:j));
                if(dp[i][l]>=m){
                    ans=min(l,ans);
                    break;
                }
            }
    printf("%d",ans);
    return 0;
}

5017: [Snoi2017]炸弹

先刷出每个炸弹在不往右炸的情况下能往左炸到哪里,然后每个点往右炸的同时更新右端点。
注意别爆long long,细节看代码
#include<cstdio>
#include<algorithm>
using namespace std;
#define ll long long
inline char tc(void){
    static char fl[10000],*A=fl,*B=fl;
    return A==B&&(B=(A=fl)+fread(fl,1,10000,stdin),A==B)?EOF:*A++;
}
inline ll read(void){
    ll a=0,f=1;static char c;
    while((c=tc())<'0'||c>'9')c=='-'?f=-1:0;
    while(c>='0'&&c<='9')a=a*10+c-'0',c=tc();
    return a*f;
}
const int Mod=1000000007;
ll ans,n,x[500001],y[500001],l[500001],r[500001];
int main(void){
    register int i,a;
    n=read();
    for(i=1;i<=n;++i)
        x[i]=read(),y[i]=read();
    for(i=1;i<=n;++i){
        l[i]=i;
        while(l[i]>1&&x[i]-x[l[i]-1]<=y[i])
            l[i]=l[l[i]-1],y[i]=max(y[i],y[l[i]]-x[i]+x[l[i]-1]);
    }
    for(i=n;i;--i){
        r[i]=i;
        while(r[i]<n&&x[r[i]+1]-x[i]<=y[i])
            r[i]=r[r[i]+1],l[i]=min(l[i],l[r[i]]);
    }
    for(i=1;i<=n;++i)
        ans=(ans+(r[i]-l[i]+1)*i)%Mod;
    printf("%d",ans);
    return 0;
}

5019: [Snoi2017]遗失的答案

lcm%gcd!=00lcmgcd
lcm=Plkk,gcd=Pgkk
xx=Pakk,Pkak[gk,lk],DFSx
1000DP

#include<cstdio>
#include<algorithm>
using namespace std;
#define ll long long 
#define Mod 1000000007
inline char tc(void){
    static char fl[100000],*A=fl,*B=fl;
    return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
inline int read(void){
    int a=0;static char c;
    while((c=tc())<'0'||c>'9');
    while(c>='0'&&c<='9')a=a*10+c-'0',c=tc();
    return a;
}
struct M{
    int x,dx,dix;
    M(int x=0,int dx=0,int dix=0):x(x),dx(dx),dix(dix){}
    inline bool operator <(const M&a)const{
        return x<a.x;
    }
}que[1000];
int n,q,l,g,cnt,p[12],num[12],tot,dp[256][256],ans[1000];
bool invalid;
void resolve(void){
    int x=l,y=g;
    for(int i=2;i*i<=x;++i)
        if(l%i==0){
            while(x%i==0&&y%i==0)
                x/=i,y/=i;
            if(x%i==0)p[++cnt]=i;
            while(x%i==0)
                ++num[cnt],x/=i;
        }
    if(x>1&&x!=y)p[++cnt]=x,++num[cnt];
    return ;
}
void dfs(int now,ll sum,int dx,int dix){
     if(sum>n)return ;
     if(now>cnt){
        que[++tot]=M(sum,dx,dix);
        return ;
     }
     ll o=1;
     for(int i=0;i<=num[now];++i,o*=p[now])
        if(i==0)dfs(now+1,sum*o,dx,dix|(1<<now-1));
        else if(i==num[now])dfs(now+1,sum*o,dx|(1<<now-1),dix);
        else dfs(now+1,sum*o,dx,dix);
    return ;
}
void solve(void){
    int i,j,k,mx=(1<<cnt)-1,t;
    sort(que+1,que+tot+1);
    dp[0][0]=1,dp[que[1].dx][que[1].dix]=1;
    for(i=2;i<=tot;++i)
        for(j=mx;j>=0;--j)
            for(k=mx;k>=0;--k)
                (dp[j|que[i].dx][k|que[i].dix]+=dp[j][k])%=Mod;
    for(int i=1;i<=tot;++i){
        t=dp[mx][mx];
        for(int j=0;j<=mx;j++)
            for(int k=0;k<=mx;k++)
                if(k!=mx||j!=mx)
                    if((j|que[i].dx)==mx&&(k|que[i].dix)==mx)t=(t-dp[j][k])%Mod;
        ans[i]=((ll)t*500000004%Mod+Mod)%Mod,ans[i]=((ll)dp[mx][mx]-ans[i]+Mod)%Mod;
    }
    return ;
}
int ef(int x){
    int l=1,r=tot,mid;
    while(l<=r){
        mid=l+r>>1;
        if(que[mid].x<=x)l=mid+1;
        else r=mid-1;
    }
    return que[l-1].x==x?l-1:0;
}
int main(void){
    register int i,x;
    n=read(),g=read(),l=read();
    if(l%g!=0)invalid=1;
    if(invalid)goto wjnsb;
    resolve(),dfs(1,g,0,0),solve();
    q=read();while(q--)x=read(),printf("%d\n",ans[ef(x)]);
    return 0;
    wjnsb:q=read();while(q--)puts("0");return 0;
}

4804: 欧拉心算

莫比乌斯反演,随便推推就出来了。
#include<cstdio>
using namespace std;
#define N 10000000
#define ll long long 
inline char tc(void){
    static char fl[100000],*A=fl,*B=fl;
    return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
inline int read(void){
    int a=0;static char c;
    while((c=tc())<'0'||c>'9');
    while(c>='0'&&c<='9')a=a*10+c-'0',c=tc();
    return a;
}
int T,n,prim[2000000],E[N+10],cnt,t,pos;
ll ans,sum[N+10];
char p[N+10];
void pre(void){
    register int i,j;
    E[1]=1;
    for(i=2;i<=N;++i){
        if(p[i]==0)prim[++cnt]=i,E[i]=i-1;
        for(j=1;j<=cnt&&(t=i*prim[j])<=N;++j){
            p[t]=1;
            if(i%prim[j]==0){
                E[t]=E[i]*prim[j];
                break;
            }
            E[t]=E[i]*(prim[j]-1);
        }
    }
    for(i=1;i<=N;++i)
        sum[i]=sum[i-1]+E[i];
    return ;
}
int main(void){
    register int i,pos;
    for(pre(),T=read();T;--T){
        n=read(),ans=0;
        for(i=1,pos;i<=n;i=pos+1)
            pos=n/(n/i),ans+=(sum[pos]-sum[i-1])*sum[n/pos];
        printf("%lld\n",ans*2-sum[n]);
    }
    return 0;
}

3085: 反质数加强版SAPGAP

%Manchery
在反素数那题的基础上加上一个优化可以草过去
看Manchery大佬的博客
我的代码就是抄的

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define clr(x,y) memset(x,y,sizeof(x))
using namespace std;
#define ll long long 
struct BIGINT{
    int a[30];
    BIGINT(void){}
    BIGINT(char *s){
        clr(a,0);
        int i,L=strlen(s),cur=0;
        for(i=L-1;i-3>=0;i-=4){
            a[cur]=(s[i-3]-'0')*1000+
                   (s[i-2]-'0')*100+
                   (s[i-1]-'0')*10+
                   (s[i]-'0');
            ++cur;
        }
        if(i<0)return ;
        if(i==0)a[cur]=s[0]-'0';
        else if(i==1)a[cur]=10*(s[0]-'0')+(s[1]-'0');
        else if(i==2)a[cur]=100*(s[0]-'0')+10*(s[1]-'0')+(s[2]-'0');
        return ;
    }
    BIGINT(int x){
        clr(a,0),a[0]=x;
        return ;
    }
    inline BIGINT operator*(int x){
        int i;
        BIGINT tmp;
        for(i=0;i<27;++i)tmp.a[i]=a[i]*x;
        for(i=0;i<26;++i){
            tmp.a[i+1]+=tmp.a[i]/10000;
            tmp.a[i]%=10000;
        }
        return tmp;
    }
    int operator<(BIGINT p){
        int i;
        for(i=26;i>=0;--i){
            if(a[i]<p.a[i])return 1;
            if(a[i]>p.a[i])return 0;
        }
        return 0;
    }
    int operator==(BIGINT p){
        int i;
        for(i=26;i>=0;--i)
            if(a[i]!=p.a[i])return 0;
        return 1;
    }
    int operator<=(BIGINT p){
        return *this==p||*this<p;
    }
    void print(void){
        int cur=26;
        while(cur>0&&0==a[cur])--cur;
        printf("%d",a[cur]);
        --cur; 
        while(cur>=0)printf("%04d",a[cur--]);
        puts("");
        return ;
    }
};

int prime[]={  
    1,  2,  3,  5,  7,
    11, 13, 17, 19, 23,
    29, 31, 37, 41, 43,
    47, 53, 59, 61, 67,
    71, 73, 79, 83, 89,
    97, 101,103,107,109,
    113,127,131,137,139,
    149,151,157,163,167,
    173,179,181,191,193,
    197,199,211,223,227,
    229,233,239,241,251
};
int K[]={  
    1,2,2,3,3,
    4,4,5,5,5,
    5,5,6,6,6,
    6,6,6,6,7,
    7,7,7,7,7,
    7,7,7,7,7,
    7,7,8,8,8,
    8,8,8,8,8,
    8,8,8,8,8,
    8,8,8,8,8,
    8,8,8,8,8
};
BIGINT n,ans;
ll m,q1,maxinum;
inline void dfs(int k,BIGINT now,ll cnt,ll last){
    if(cnt>maxinum||cnt==maxinum&&now<ans)
        ans=now,maxinum=cnt;
    if(k!=1)
        last=min(last,q1/(K[k]-1));
    ll tmp=cnt;
    for(int i=1;i<=last;++i){
        if(k==1)q1=i;
        tmp+=cnt;
        now=now*prime[k];
        if(n<now)break;
        dfs(k+1,now,tmp,i);
    }
    return ;
}
char s[105];
int main(void){
    register int i;
    scanf("%s",s),
    n=BIGINT(s);
    if(n==BIGINT(1))
        return puts("1"),0;
    BIGINT itmp=BIGINT(1);
    for(;itmp<=n;)itmp=itmp*prime[++m];
    dfs(1,BIGINT(1),1,2*K[m]-1-1);
    ans.print();
    return 0;
}

51nod

1076 2条不相交的路径

边双裸题
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline char tc(void){
    static char fl[10000],*A=fl,*B=fl;
    return A==B&&(B=(A=fl)+fread(fl,1,10000,stdin),A==B)?EOF:*A++;
}
inline int read(void){
    int a=0;static char c;
    while((c=tc())<'0'||c>'9');
    while(c>='0'&&c<='9')a=a*10+c-'0',c=tc();
    return a;
}
int n,m,q,tot,time,low[25100],pre[25100];
struct Edge{
    int to,bridge;
    Edge *next;
}e[100001],*link[52003];
inline void add(int x,int y){
    e[++tot].to=y,e[tot].next=link[x],link[x]=&e[tot];
    return ;
}
void dfs(int u,int fa){
    low[u]=pre[u]=++time;
    for(Edge *i=link[u];i;i=i->next){
        if(!pre[i->to]){
            dfs(i->to,u);
            low[u]=min(low[i->to],low[u]);
            if(pre[u]<low[i->to])
                i->bridge=1;
        }else if(fa!=i->to)
            low[u]=min(low[u],pre[i->to]);
    }
    return ;
}
void dfs(int u){
    pre[u]=time;
    for(Edge *i=link[u];i;i=i->next){
        if(i->bridge||pre[i->to])continue;
        dfs(i->to);
    }
    return ;
}
int main(void){
    register int i,x,y;
    n=read(),m=read();
    for(i=1;i<=m;++i)
        x=read(),y=read(),add(x,y),add(y,x);
    time=0;
    for(i=1;i<=n;++i)
        if(!pre[i])
            dfs(i,0);
    time=0;
    memset(pre,0,sizeof(pre));
    for(i=1;i<=n;++i)
        if(!pre[i])
            ++time,dfs(i);
    q=read();
    while(q--){
        x=read(),y=read();
        if(pre[x]==pre[y])puts("Yes");
        else puts("No");
    }
    return 0;
}

1033 骨牌覆盖 V2

轮廓线DP+矩乘快速幂
#include<cstdio>
using namespace std;
#define ll long long
#define Mod 1000000007
ll n,m,now,k[32][32],ans;
struct Y{
    ll k[32][32];
    Y operator *(Y a){
        Y b;
        for(int i=0;i<(1<<n);++i)
            for(int j=0;j<(1<<n);++j){
                b.k[i][j]=0;
                for(int l=0;l<(1<<n);++l)
                    (b.k[i][j]+=k[i][l]*a.k[l][j])%=Mod;    
            }
        return b;
    }
}o;
struct M{
    ll k[32];
    M operator *(Y a){
        M b;
        for(int i=0;i<1<<n;++i)
            b.k[i]=0;
        for(int i=0;i<(1<<n);++i)
            for(int l=0;l<(1<<n);++l)
                (b.k[i]+=k[l]*a.k[i][l])%=Mod;
        return b;
    }
}l;
void dfs(int x,int sum){
    if(x>n){
        ++k[now][sum];
        return ;
    }
    if(sum&(1<<x-1))
        dfs(x+1,sum-(1<<x-1));
    else
        dfs(x+1,sum+(1<<x-1));
    if(x!=n&&!(sum&(1<<x-1))&&!(sum&(1<<x)))
        dfs(x+2,sum);
    return ;
}
M ksm(Y a,int b){
    M s;
    for(int i=1;i<1<<n;++i)
        s.k[i]=0;
    s.k[0]=1;
    while(b){
        if(b&1)s=s*a;
        a=a*a;
        b>>=1;
    }
    return s;
}
int main(void){
    register int i,j;
    scanf("%d%d",&m,&n);
    for(now=0;now<1<<n;++now)
        dfs(1,now);
    for(i=0;i<1<<n;++i)
        for(j=0;j<1<<n;++j)
            o.k[i][j]=k[i][j];
    l=ksm(o,m);
    printf("%lld",l.k[0]);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值