AtCoder Beginner Contest 164题解

题目链接

A.Sheep and Wolves

题意:
s 个 羊 , w 个 狼 , 羊 如 果 多 是 安 全 的 , 否 则 是 不 安 全 的 s个羊,w个狼,羊如果多是安全的,否则是不安全的 sw
题解:
直 接 比 较 输 出 即 可 直接比较输出即可
AC代码

#include
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int mod=1e9+7;
//const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=1e6+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};


int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int s,w;
    cin>>s>>w;
    if(w>=s)cout<<"unsafe";
    else cout<<"safe";

    return 0;
}



B. Battle

题意:
A 有 a 的 生 命 值 , b 的 攻 击 力 A有a的生命值,b的攻击力 Aab
B 有 c 的 生 命 值 , d 的 攻 击 力 B有c的生命值,d的攻击力 Bcd
A 先 手 , 两 人 轮 流 攻 击 , 生 命 值 降 到 0 及 以 下 就 失 败 A先手,两人轮流攻击,生命值降到0及以下就失败 A0
如 果 A 赢 输 出 y e s , 否 则 n o 如果A赢输出yes,否则no Ayesno
题解:
由 于 a , b , c , d < = 100 , 数 据 都 不 大 由于a,b,c,d<=100,数据都不大 a,b,c,d<=100
直 接 暴 力 模 拟 每 个 人 的 攻 击 即 可 , 看 谁 先 失 败 直接暴力模拟每个人的攻击即可,看谁先失败
AC代码

#include
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int mod=1e9+7;
//const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=1e6+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};


int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int a,b,c,d;
    cin>>a>>b>>c>>d;
    int cnt=1;
    while(a>0&&c>0){
        if(cnt&1)c-=b;
        else a-=d;
        cnt^=1;
    }
    if(a<=0)cout<<"No";
    else cout<<"Yes";
    return 0;
}



C.gacha

题意:
给 你 n 个 字 符 串 , 多 少 个 不 一 样 的 字 符 串 给你n个字符串,多少个不一样的字符串 n
题解:
直 接 s e t 维 护 字 符 串 , 输 出 s i z e 即 可 直接set维护字符串,输出size即可 setsize
AC代码

#include
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int mod=1e9+7;
//const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=1e6+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};


int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    set<string> s;
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
        string x;
        cin>>x;
        s.insert(x);
    }
    cout<<s.size();
    return 0;
}



D. Multiple of 2019

题意:
给 一 个 长 度 < = 1 e 6 的 数 给一个长度<=1e6的数 <=1e6
任 取 i , j 保 证 i < = j 使 得 从 i 到 j 组 成 的 数 是 2019 的 倍 数 任取i,j保证i<=j使得从i到j组成的数是2019的倍数 i,ji<=j使ij2019
问 有 多 少 组 i , j 问有多少组i,j ij
题解:
倒 着 每 次 加 一 位 数 , 加 上 后 看 前 面 加 的 数 有 多 少 个 向 2019 取 余 和 现 在 相 同 的 数 倒着每次加一位数,加上后看前面加的数有多少个向2019取余和现在相同的数 2019
把 前 面 那 一 段 减 去 , 即 是 2019 的 倍 数 把前面那一段减去,即是2019的倍数 2019
所 以 用 一 个 m a p 维 护 一 个 倒 着 枚 举 时 候 每 一 个 后 缀 数 的 余 数 所以用一个map维护一个倒着枚举时候每一个后缀数的余数 map
维 护 的 同 时 并 加 上 这 之 前 出 现 过 的 相 同 的 余 数 维护的同时并加上这之前出现过的相同的余数
由 于 可 能 一 段 后 缀 都 是 2019 的 倍 数 , 所 以 把 0 这 个 位 置 余 数 先 加 一 由于可能一段后缀都是2019的倍数,所以把0这个位置余数先加一 20190
AC代码

#include
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int mod=1e9+7;
//const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=1e6+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};


int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    string s;
    cin>>s;
    int p=2019;
    map<int,ll> m;
    m[0]++;
    ll ans=0,sum=0,d=1;
    for(int i=s.length()-1;i>=0;i--){
        sum=(sum+d*(s[i]-'0')%p)%p;
        ans+=m[sum];
        m[sum]++;
        d=(d*10)%p;
    }
    cout<<ans;
    return 0;
}



E.Two Currencies

题意:
有 n 个 点 , m 条 路 , 你 有 无 数 金 和 s 银 有n个点,m条路,你有无数金和s银 nm,s
每 条 路 的 花 费 为 a i 银 , b i 时 间 , 不 能 使 用 金 每条路的花费为a_i银,b_i时间,不能使用金 ai,bi使
每 个 点 都 有 交 换 站 , 可 以 把 1 金 换 成 c i 银 , 花 费 d i 分 钟 每个点都有交换站,可以把1金换成c_i银,花费d_i分钟 1cidi
问 你 从 1 到 每 个 点 ( 2 , 3 , … … , n ) 都 需 要 多 少 时 间 问你从1到每个点(2,3,……,n)都需要多少时间 123n
题解:
n , a i < = 50 , b i , c i , d i < = 1 e 9 , s < = 1 e 9 n,a_i<=50,bi,ci,di<=1e9,s<=1e9 n,ai<=50,bi,ci,di<=1e9,s<=1e9
很 明 显 可 以 观 察 出 来 , 最 多 只 需 要 2500 银 就 可 以 去 任 何 地 方 很明显可以观察出来,最多只需要2500银就可以去任何地方 2500
所 以 分 类 讨 论 一 下 , 如 果 手 里 有 2500 银 所以分类讨论一下,如果手里有2500银 2500
你 可 以 去 任 何 地 方 , 那 么 这 道 题 就 是 一 个 最 普 通 的 d i j s k t r a 你可以去任何地方,那么这道题就是一个最普通的dijsktra dijsktra
不 用 考 虑 钱 的 事 , 只 用 考 虑 一 下 路 上 花 费 的 时 间 不用考虑钱的事,只用考虑一下路上花费的时间
如 果 手 里 不 够 这 么 多 , 那 么 就 是 一 个 汽 车 加 油 问 题 如果手里不够这么多,那么就是一个汽车加油问题
用 一 个 数 组 d i s [ i ] [ j ] 维 护 到 达 的 点 和 此 时 手 里 的 银 已 经 花 费 的 时 间 用一个数组dis[i][j]维护到达的点和此时手里的银已经花费的时间 dis[i][j]
如 果 能 够 到 达 下 个 点 就 进 行 松 弛 操 作 如果能够到达下个点就进行松弛操作
在 最 后 的 时 候 在 该 点 进 行 换 钱 操 作 , 将 金 换 成 银 , 直 到 换 的 数 量 超 过 2500 在最后的时候在该点进行换钱操作,将金换成银,直到换的数量超过2500 2500
如 果 超 过 的 全 部 按 2500 算 , 因 为 2500 可 以 走 完 全 部 如果超过的全部按2500算,因为2500可以走完全部 25002500
最 后 对 于 每 个 点 , 在 0 到 2500 的 当 前 银 里 找 到 最 小 值 即 可 最后对于每个点,在0到2500的当前银里找到最小值即可 02500
AC代码

#include
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int mod=1e9+7;
//const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=1e6+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};

struct edge{
    int v,nx;
    ll a,b;
}e[210];
int head[60],cnt;
ll c[60],d[60];
ll dis[60][3000];
void add(int u,int v,ll a,ll b){
    e[++cnt].v=v;
    e[cnt].a=a;
    e[cnt].b=b;
    e[cnt].nx=head[u];
    head[u]=cnt;
}
struct node{
    int u;
    ll s,t;
    bool operator <(const node &x)const{
        return t>x.t;
    }
};
ll dis1[100];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int n,m;
    ll s;
    cin>>n>>m>>s;
    for(int i=1;i<=m;i++){
        int u,v;
        ll a,b;
        cin>>u>>v>>a>>b;
        add(u,v,a,b);
        add(v,u,a,b);
    }
    for(int i=1;i<=n;i++)cin>>c[i]>>d[i];
    if(s>2500){
        for(int i=1;i<=n;i++)dis1[i]=inf*inf;
        dis1[1]=0;
        priority_queue<pii,vector<pii>,greater<pii> > q;
        q.push(mp(0,1));
        while(!q.empty()){
            pii p=q.top();
            q.pop();
            int u=p.se;
            if(dis1[u]<p.fi)continue;
            for(int i=head[u];i;i=e[i].nx){
                int v=e[i].v;
                if(dis1[v]>dis1[u]+e[i].b){
                    dis1[v]=dis1[u]+e[i].b;
                    q.push(mp(dis1[v],v));
                }
            }
        }
        for(int i=2;i<=n;i++)
            cout<<dis1[i]<<endl;
        return 0;
    }
    priority_queue<node> q;
    for(int i=1;i<=n;i++)
        for(int j=0;j<=50*n;j++)
            dis[i][j]=1e18;
    dis[1][s]=0;
    q.push((node){1,s,0});
    while(!q.empty()){
        node p=q.top();
        q.pop();
        int u=p.u;
        if(p.t>dis[u][p.s])continue;
        for(int i=head[u];i;i=e[i].nx){
            int v=e[i].v;
            if(p.s>=e[i].a&&dis[v][p.s-e[i].a]>dis[u][p.s]+e[i].b){
                dis[v][p.s-e[i].a]=dis[u][p.s]+e[i].b;
                q.push((node){v,p.s-e[i].a,dis[u][p.s]+e[i].b});
            }
        }
        ll ts=min(p.s+c[u],50ll*n);
        if(dis[u][ts]>dis[u][p.s]+d[u]){
            dis[u][ts]=dis[u][p.s]+d[u];
            q.push((node){u,ts,dis[u][p.s]+d[u]});
        }
    }
    for(int i=2;i<=n;i++){
        ll ans=1e18;
        for(int j=0;j<=50*n;j++)
            ans=min(ans,dis[i][j]);
        cout<<ans<<endl;
    }
    return 0;
}


你可能感兴趣的:(AtCoder Beginner Contest 164题解)