ACM-ICPC 2018 沈阳赛区网络预赛

A. Gudako and Ritsuka

留坑

 

B. Call of Accepted

题意:给你一些运算,包括+-*()d,d的运算是2d6=2  和  2*6,然后输出最小值和最大值

思路:按照题意模拟即可,可以用pair来存储最小值和最大值

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#include<map>
using namespace std;
#define INF 0x3f3f3f3f
#define eps 1e-10
#define PI acos(-1.0)
#define _e exp(1.0)
#define ll long long
const ll mod = 1e9+7;
const int maxn = 1e5 + 5;
int len;
int fst[1005];
char str[1005];

pair<int,int> add(pair<int,int>p1,pair<int,int>p2)//加法
{
    return make_pair(p1.first+p2.first,p1.second+p2.second);
}
pair<int,int> sub(pair<int,int>p1,pair<int,int>p2)//减法,小的是p1的小的减p2的大的,大的是p1的小的减p2的大的
{
    return make_pair(p1.first-p2.second,p1.second-p2.first);
}
pair<int,int> mul(pair<int,int>p1,pair<int,int>p2)//乘法简单的不可行,可以把四种情况都取出来,然后比大小放进pair里
{
    int t1=p1.first*p2.first;
    int t2=p1.first*p2.second;
    int t3=p1.second*p2.first;
    int t4=p1.second*p2.second;
    return make_pair(min(min(t1,t2),min(t3,t4)),max(max(t1,t2),max(t3,t4)));
}
pair<int,int> pp(pair<int,int>p1,pair<int,int>p2)//就是题目里的运算符d,p1是第一个数,p2是第一个数*第二个数
{
    return make_pair(p1.first,p1.second*p2.second);
}
pair<int,int> judge(int begin,int end)
{
    int i;
    pair<int,int> k;
    for(i=begin;i<=end;i++)
    {
        if(str[i]=='+' && fst[i]==fst[begin])
        {
            k=add(judge(begin,i-1),judge(i+1,end));
            return k;
        }
    }
    for(i=end;i>=begin;i--)
    {
        if(str[i]=='-' && fst[i]==fst[begin])
        {
            k=sub(judge(begin,i-1),judge(i+1,end));
            return k;
        }
    }
    for(i=begin;i<=end;i++)
    {
        if(str[i]=='*' && fst[i]==fst[begin])
        {
            k=mul(judge(begin,i-1),judge(i+1,end));
            return k;
        }
    }
    for(int i=end;i>=begin;i--)
    {
        if(str[i]=='d' && fst[i]==fst[begin])
        {
            k=pp(judge(begin,i-1),judge(i+1,end));
            return k;
        }
    }
    if(str[begin]=='(')
    {
        for(i=begin+1;fst[i]>=fst[begin+1];i++);
        k=judge(begin+1,i-1);
    }
    else
    {
        int n=0;
        for(int i=begin;i<=end;i++)
        {
            if(!(str[i]>='0' && str[i]<='9'))
                break;
            n=n*10+str[i]-'0';
        }
        k=make_pair(n,n);
    }
    return k;
}

int main()
{
    int i;
    while(cin>>str)
    {
        memset(fst,0,sizeof(fst));
        len=strlen(str);
        fst[0]=1;
        for(i=1;i<=len-1;i++)
        {
            if(str[i-1]=='(')
                fst[i]=fst[i-1]+1;
            else if(str[i]==')')
                fst[i]=fst[i-1]-1;
            else
                fst[i]=fst[i-1];
        }
        pair<int,int> ans=judge(0,len-1);
        printf("%d %d\n",ans.first,ans.second);
    }
    return 0;
}
View Code

 

 

C. Convex Hull

留坑

 

 D. Made In Heaven

题意:求第k短路是否大于T

思路:A*算法,启发式搜索

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<set>
#include<stack>
#include<vector>
using namespace std;
#define INF 0x3f3f3f3f
#define eps 1e-10
#define PI acos(-1.0)
#define _e exp(1.0)
#define ll long long
const int maxn=10010;
const ll mod = 1e9 + 7;

struct node
{
    int to;
    int val;
    int next;
};
struct node2
{
    int to;
    int g,f;
    bool operator<(const node2 &r) const
    {
        if(r.f==f)
            return r.g<g;
        return r.f<f;
    }
};
node edge[maxn],edge2[maxn];
int n,m,s,t,k,cnt,cnt2,ans;
int dis[1010],vis[1010],head[1010],head2[1010];
void init()
{
    memset(head,-1,sizeof(head));
    memset(head2,-1,sizeof(head2));
    cnt=cnt2=1;
}
void addedge(int from,int to,int val)
{
    edge[cnt].to=to;
    edge[cnt].val=val;
    edge[cnt].next=head[from];
    head[from]=cnt++;
}
void addedge2(int from,int to,int val)
{
    edge2[cnt2].to=to;
    edge2[cnt2].val=val;
    edge2[cnt2].next=head2[from];
    head2[from]=cnt2++;
}
bool spfa(int s,int n,int head[],node edge[],int dist[])
{
    queue<int>que;
    int inq[1010];
    for(int i=0;i<=n;i++)
    {
        dis[i]=INF;
        inq[i]=0;
    }
    dis[s]=0;
    que.push(s);
    inq[s]++;
    while(!que.empty())
    {
        int q=que.front();
        que.pop();
        inq[q]--;
        if(inq[q]>n)
            return false;
        int k=head[q];
        while(k>=0)
        {
            if(dist[edge[k].to]>dist[q]+edge[k].val)
            {
                dist[edge[k].to]=edge[k].val+dist[q];
                if(!inq[edge[k].to])
                {
                    inq[edge[k].to]++;
                    que.push(edge[k].to);
                }
            }
            k=edge[k].next;
        }
    }
    return true;
}
int T;
bool A_star(int s,int t,int n,int k,int head[],node edge[],int dist[])
{
    node2 e,ne;
    int cnt=0;
    priority_queue<node2>que;
    if(s==t)
        k++;
    if(dis[s]==INF)
        return false;
    e.to=s;
    e.g=0;
    e.f=e.g+dis[e.to];
    que.push(e);
    while(!que.empty())
    {
        e=que.top();
        que.pop();
        if(e.to==t)
            cnt++;
        if(cnt==k)
            return e.g<=T;
        for(int i=head[e.to];i!=-1;i=edge[i].next)
        {
            ne.to=edge[i].to;
            ne.g=e.g+edge[i].val;
            ne.f=ne.g+dis[ne.to];
            if(ne.g>T)
                continue;
            que.push(ne);
        }

    }
    return false;

}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        scanf("%d%d%d",&s,&t,&k);
        scanf("%d",&T);
        init();
        for(int i=1;i<=m;i++)
        {
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            addedge(a,b,c);
            addedge2(b,a,c);
        }
        spfa(t,n,head2,edge2,dis);
        if(!A_star(s,t,n,k,head,edge,dis))
            puts("Whitesnake!");
        else
            puts("yareyaredawa");
    }
    return 0;
}
View Code

 

 

E. The cake is a lie

留坑

 

F. Fantastic Graph

题意:

 一个二分图,左边有n个点,右边有m个点,一共有k条边分别连接左右两个点,问能否取这k条边中部分边,使得所有点的度数都在l~r范围内。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#include<map>
using namespace std;
#define INF 0x3f3f3f3f
#define eps 1e-10
#define PI acos(-1.0)
#define _e exp(1.0)
#define ll long long
const ll mod = 1e9+7;
const int maxn = 1e5 + 5;
const  int MAXN=10010;
const int MAXM=40010;
struct edge
{
    int to,next,cap,flow;
}edge[MAXM];
int tol;
int head[MAXN];
int gap[MAXN],dep[MAXN],pre[MAXN],cur[MAXN];
void init()
{
    tol=0;
    memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int w,int rw=0)
{
    edge[tol].to=v;edge[tol].cap=w;edge[tol].next=head[u];
    edge[tol].flow=0;head[u]=tol++;
    edge[tol].to=u;edge[tol].cap=rw;edge[tol].next=head[v];
    edge[tol].flow=0;head[v]=tol++;
}
int sap(int start,int end,int N)
{
    memset(gap,0,sizeof(gap));
    memset(dep,0,sizeof(dep));
    memcpy(cur,head,sizeof(head));
    int u=start;
    pre[u]=-1;
    gap[0]=N;
    int ans=0;
    while(dep[start]<N)
    {
        if(u==end)
        {
          int Min=INF;
          for(int i=pre[u];i!=-1;i=pre[edge[i^1].to])
             if(Min>edge[i].cap-edge[i].flow)
                 Min=edge[i].cap-edge[i].flow;
         for(int i=pre[u];i!=-1;i=pre[edge[i^1].to])
         {
             edge[i].flow+=Min;
             edge[i^1].flow-=Min;
         }
         u=start;
         ans+=Min;
        continue;
    }
    bool flag=false;
    int v;
    for(int i=cur[u];i!=-1;i=edge[i].next)
    {
        v=edge[i].to;
        if(edge[i].cap-edge[i].flow && dep[v]+1 == dep[u])
        {
            flag=true;
            cur[u]=pre[v]=i;
            break;
        }
    }
    if(flag)
    {
        u=v;
        continue;
    }
    int Min=N;
    for(int i=head[u];i!=-1;i=edge[i].next)
        if(edge[i].cap-edge[i].flow && dep[edge[i].to]<Min)
        {
            Min=dep[edge[i].to];
            cur[u]=i;
        }
    gap[dep[u]]--;
    if(!gap[dep[u]])
        return ans;
    dep[u]=Min+1;
    gap[dep[u]]++;
    if(u!=start )
        u=edge[pre[u]^1].to;
    }
    return ans;
}
int S,T;
vector<int>ee;
void add(int u,int v,int low,int high)
{
    addedge(u,v,high-low);
    if(low>0)
    {
        addedge(S, v, low);
        ee.push_back(tol-2);
        addedge(u, T, low);
        ee.push_back(tol-2);
    }
}
bool check()
{
    for(int i=0;i<ee.size();i++)
    {
        int e=ee[i];
        if(edge[e].flow !=edge[e].cap)
            return false;
    }
    return true;
}

int main()
{
    int N,M,K;
    int ca=0;
    while(scanf("%d%d%d",&N,&M,&K)==3)
    {
        ee.clear();
        ca++;
        int L,R;
        scanf("%d%d",&L,&R);
        init();
        S=N+M+2;
        T=N+M+3;
        for(int i=1;i<=N;i++)
            add(0,i,L,R);
        for(int i=N+1;i<=N+M;i++)
            add(i, N+M+1, L, R);
        int u,v;
        while(K--)
        {
            scanf("%d%d",&u,&v);
            addedge(u, v+N, 1);
        }
        addedge(N+M+1, 0, INF);
        sap(S,T,T+1);
        if(check())
            printf("Case %d: Yes\n",ca);
        else
            printf("Case %d: No\n",ca);
    }
    return 0;
}
View Code

 

 

G. Spare Tire

题意:给定1<=i<=n ; 要求i与m互质,求出i*i+i的累积总和

思路:

由a的递推式可以很容易地得到ai=i*(i+1)

求所有满足条件的数不好求,我们可以用所有的减去不满足条件的,即与m不互素的数贡献的a值

根据算数基本定理将m分解,与m不互素的就是至少有其中一个因子,算所有的所以要容斥

对于每个因子积sum,会形成sum,2*sum,3*sum...[n/sum]*sum这些不互素的数,

设k=[n/sum]

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#include<map>
using namespace std;
#define INF 0x3f3f3f3f
#define eps 1e-10
#define PI acos(-1.0)
#define _e exp(1.0)
#define ll long long
const ll mod = 1e9+7;
const int maxn = 1e5 + 5;
ll prime[10100];
int pl=0;
bool vis[10010];
ll n,m;
void getprime()
{
    for(ll i=2;i<10010;i++)
    {
        if(vis[i]==false)
        {
            prime[++pl]=i;
        }
        for(int j=1;j<pl && i*prime[j]<10010;j++)
        {
            vis[i*prime[j]]=true;
            if(i % prime[j]==0)
                break;
        }
    }
}
ll num[15];
int tot;
void bre(ll n)
{
    tot=0;
    for(int i=1;i<pl && prime[i]*prime[i]<=n;i++)
    {
        if(n%prime[i]==0)
        {
            num[tot++]=prime[i];
            while(n%prime[i]==0)
            {
                n/=prime[i];
            }
        }
        if(n==1)
            break;
    }
    if(n!=1)
        num[tot++]=n;
}
ll inv2,inv3,inv6;
ll fpow(ll a,ll b)
{
    ll ans=1;
    ll tmp=a%mod;
    while(b)
    {
        if(b&1)
            ans=ans*tmp%mod;
        tmp=tmp*tmp%mod;
        b/=2;
    }
    return ans;
}
void solve()
{
    ll ans=0;
    for(int i=0;i<(1<<tot);i++)
    {
        int cnt=0;
        ll sum=1;
        for(int j=0;j<tot;j++)
        {
            if(i&(1<<j))
            {
                cnt++;
                sum*=num[j];
            }
        }
        ll k=n/sum;
        sum%=mod;
        ll p=(1+k)*k%mod*inv2%mod*sum%mod;
        ll q=k*(1+k)%mod*(2*k+1)%mod*inv6%mod*sum%mod*sum%mod;
        if(cnt&1)
        {
            ans-=p;
            if(ans<0)
                ans+=mod;
            ans-=q;
            if(ans<0)
                ans+=mod;
        }
        else
        {
            ans=(ans+p);
            if(ans>mod)
                ans-=mod;
            ans+=q;
            if(ans>mod)
                ans-=mod;
        }
    }
    printf("%lld\n",ans);
}
int main()
{
    getprime();
    inv2=fpow(2,mod-2);
    inv6=fpow(6,mod-2);
    while(~scanf("%lld%lld",&n,&m))
    {
        bre(m);
        solve();
    }
}
View Code

 

 

 

H. Hamming Weight

留坑

 

I. Lattice's basics in digital electronics

题意:给出一个映射关系左为ascll值,右为密码,然后给出一个16进制的数,要求先将16进制转化为2进制然后每9位通过奇偶校验判断,若前8位有奇数个1并且第9位为0则通过奇偶校验,若前8位有偶数个1且第9 位为1也通过奇偶校验。取出的串在映射中进行查找,输出对应ascll值的字符。

思路:可以用map来找取编码对应的值,网上好像也有人用字典树的,应该都可以的吧,然后奇偶校验可以用异或值来进行判断。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#include<map>
using namespace std;
#define INF 0x3f3f3f3f
#define eps 1e-10
#define PI acos(-1.0)
#define _e exp(1.0)
#define ll long long
const int maxn = 1e5 + 5;
map<string,int>mp;
char str[200010];
int a[1000010];
int b[1000010];
char ss[20];

int getV(char ch)
{
    if(ch>='A' && ch<='Z')
        return ch-'A'+10;
    if(ch>='a' && ch<='z')
        return ch-'a'+10;
    else
        return ch-'0';
}
int main()
{
    int T;
    int M,N;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&M,&N);
        int v;
        mp.clear();
        string sss;
        while(N--)
        {
            scanf("%d",&v);
            cin>>sss;
            mp[sss]=v;     //将二进制与对应的ascll码对应
        }
        scanf("%s",str);
        int len=strlen(str);
        int cnta=0;
        for(int i=0;i<len;i++)
        {
            int v=getV(str[i]);
            a[cnta++]=v/8%2;
            a[cnta++]=v/4%2;
            a[cnta++]=v/2%2;
            a[cnta++]=v/1%2;      //十六进制转化为二进制
        }
        int cntb=0;
        for(int i=0;i+9<=cnta;i+=9)
        {
            int tmp=0;
            for(int j=0;j<9;j++)   //取异或值来验证奇偶校验
                tmp^=a[i+j];
            if(!tmp)
                continue;
            for(int j=0;j<8;j++)     //放入b数组
                b[cntb++]=a[i+j];
        }
        string now="";
        for(int i=0;i<cntb;i++)
        {
            if(M==0)
                break;
            now+=(char)(b[i]+'0');   //把b数组转换为char类型的
            if(mp.count(now))
            {
                printf("%c",mp[now]);     //如果有存在的已经定义好的编码就输出
                M--;
                if(M==0)
                    break;
                now="";
            }
        }
        printf("\n");
    }
    return 0;
}
View Code

 

 

J. Ka Chang

留坑

 

K. Supreme Number

题意:输出小于等于n的超级质数,超级质数是它的任何子序列都是质数。

思路:比赛的时候一开始看成字串找了好久的bug。考虑到答案中任意一位都必须是1或质数,可知答案只可能由1、2、3、5、7构成。由于任意两个不为1的数字构成 的两位数一定可以被11整除,所以答案中除1外的数字只能出现一次;1最多出现2次,因为111可以被3整除;而2、5、7三者一定不会有两者同时出现。因此满足条件的整数不会超过四位,全部预处理出来即可。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<set>
#include<stack>
#include<vector>
using namespace std;
#define INF 0x3f3f3f3f
#define eps 1e-10
#define PI acos(-1.0)
#define _e exp(1.0)
#define ll long long
const int maxn=50;
const ll mod = 1e9 + 7;

int a[]={1,2,3,5,7,11,13,17,23,31,37,53,71,73,113,131,137,173,311,317};
int main()
{
    int t;
    int ca=1;
    scanf("%d",&t);
    while(t--)
    {
        int ans;
        char str[105];
        scanf("%s",str);
        if(strlen(str)>=5)
            ans=317;
        else
        {
            int num=0;
            num=atoi(str);
            for(int i=0;i<20;i++)
            {
                if(num>=317)
                {
                    ans=317;
                    break;
                }
                else if(num<a[i] && num<317)
                {
                    ans=a[i-1];
                    break;
                }
            }
        }
        printf("Case #%d: %d\n",ca++,ans);
    }
}
View Code

 

posted @ 2018-09-08 20:22  千摆渡Qbd  阅读(396)  评论(0编辑  收藏  举报