csp-s模拟赛191104

problem A:

首先看到题,肯定想到的就是一个类似完全背包的问题。

用f[i]表示i能否用a[i]中的数组成。

数据已经保证数组a有序,于是我们考虑,我们考虑每一个数能否被它前面的数组成。

若x能被前i个数组成,且组成x的数当中包含a[i],则x-a[i]也能被前i个数组成。

那么容易得到转移方程f[j] |= f[j-a[i]]

于是我们就可以这样做:

#include<bits/stdc++.h>
using namespace std;
inline int read(){
    int data=0,w=1;char ch=0;
    while(ch!='-' && (ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')w=-1,ch=getchar();
    while(ch>='0' && ch<='9')data=data*10+ch-'0',ch=getchar();
    return data*w;
}
const int maxn=10010;
int a[maxn],f[maxn];
int n,q;
int main(){
    n=read();
    for(int i=1;i<=n;i++)a[i]=read();
    f[0]=1;
    for(int i=1;i<=n;i++)
        for(int j=a[i];j<=maxn;j++)
            f[j]=f[j]|f[j-a[i]];
    q=read();
    int x;
    while(q--){
        x=read();
        if(f[x])puts("Acesrc!");
        else puts("Acesrc?");
    }
    return 0;
}

这样我们就拿到了50pts的部分分,因为再想开大也是拿不到分的了,256MB稳定可以开的数组是5e7

于是我们考虑其它做法,我们考虑最小合法表示。

如果一个数>=最小合法表示,那么它就可以被a数组中的元素表示成,否则就不行。

a数组是有序的,最小的是a[1],我们就把一个数表示成k*a[1]+i。

任何数都可以表示成k*a[1]+i,如果能拼成k*a[1]+i,也就可以拼成(k+1)*a[1]+i。

于是我们用f[i]表示最小的合法的能够表示成k*a[1]+i的数是什么。

把每个f[i]视为一个点,问题就转化成了求f[0]到所有点的最短路。

代码:

 

#include<bits/stdc++.h>
#define getchar gc
using namespace std;
char buf[1000010],*pos,*End;
inline char gc(){
    if(pos==End){
        End=(pos=buf)+fread(buf,1,1000000,stdin);
        if(pos==End)return EOF;
    }return *pos++;
}
inline int read(){
    int data=0,w=1;char ch=0;
    while(ch!='-' && (ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')w=-1,ch=getchar();
    while(ch>='0' && ch<='9')data=data*10+ch-'0',ch=getchar();
    return data*w;
}
const int N=1e4+5;
int n,q,a[N],dis[N],vis[N];
priority_queue<pair<int,int> > heap;
void dijkstra(int s){
    memset(dis,0x3f,sizeof dis);
    memset(vis,0,sizeof vis);
    dis[s]=0;
    heap.push(make_pair(-dis[s],s));
    while(heap.size()){
        int x=heap.top().second;heap.pop();
        vis[x]=1;
        for(int i=1;i<=n;i++){
            int y=(x+a[i])%a[1];//下一个数字
            if(!vis[y] && dis[y]>dis[x]+a[i]){
                dis[y]=dis[x]+a[i];
                heap.push(make_pair(-dis[y],y));
            }
        }
    }
}
int main(){
    n=read();
    for(int i=1;i<=n;i++)
        a[i]=read();
    dijkstra(0);
    q=read();
    for(int i=1;i<=q;i++){
        int x=read();
        if(x>=dis[x%a[1]])puts("Acesrc!");
        else puts("Acesrc?");
    }
    return 0;
}

 

problem B:

 

posted @ 2019-11-04 15:14  LightHouseOfficial  阅读(5)  评论(0编辑  收藏  举报