ZJNU-2020-12-11

A-Array

B-Building Blocks

C-Cats

题意:

构造一个长度为n的数组。任意两只拥有相同高度的猫不能住在相邻的猫舍,并且他们之间的的猫的最小高度不能这两只相同高度的猫。

solution:

1
2 1 2
3 2 3 1 3 2 3
这样构造下去。

D-Delete Prime

题意:

给定一个长度为n的数组。
每伦将1和素数位置的数取出放到另一个数组中。然后将剩下的下标改变,但数字不变,继续取1和素数位置的数取出的操作。

1 n k,求值为k的下标
2 n k,求新的数组下表为k的值

solution:

将1e6的数的1和素数位置分批次取出,然后二分求取。

#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;
typedef pair<int,int>P;
int prime[1000005],cnt=0;
int vis[1000005];
vector<int> e[100000];
set<int>st;
int t;
int main()
{
   
    prime[cnt++]=1;
    st.insert(1);
    for(int i=2;i<=1000000;i++)
    {
   
        st.insert(i);
        if(!vis[i])
        {
   
            prime[cnt++]=i;
            for(int j=i;j<=1000000;j+=i)
                vis[j]=1;
        }
    }
    int c=0;
    while(st.size()>0)
    {
   
        int i=0,cc=1;
        for(set<int>::iterator it=st.begin();it!=st.end();it++)
        {
   
            if(cc==prime[i])
            {
   
                e[c].push_back(*it);
                i++;
            }
            cc++;
        }
        i=0;
        while(i<e[c].size())
        {
   
            st.erase(st.find(e[c][i]));
            i++;
        }
        e[c].push_back(INF);
        c++;
    }
    scanf("%d",&t);
    while(t--)
    {
   
        int op,n,k;
        scanf("%d%d%d",&op,&n,&k);
        if(op==1)
        {
   
            int res=0;
            for(int i=0;i<c;i++)
            {
   
                int pos=lower_bound(e[i].begin(),e[i].end(),k)-e[i].begin();
                if(e[i][pos]==k)
                {
   
                    printf("%d\n",res+pos+1);
                    break;
                }
                pos=lower_bound(e[i].begin(),e[i].end(),n)-e[i].begin();
                if(e[i][pos]>n)pos--;
                res+=pos+1;
            }
        }
        else if(op==2)
        {
   
            for(int i=0;i<c;i++)
            {
   
                int pos=lower_bound(e[i].begin(),e[i].end(),n)-e[i].begin();
                if(e[i][pos]>n)pos--;
                if(pos+1>=k)
                {
   
                    printf("%d\n",e[i][k-1]);
                    break;
                }
                k=k-pos-1;
            }
        }
    }
    return 0;
}

E-Eliminate the Virus

F-Flee from Maze

G-Grid Coloring

H-Happy Morse Code

题意:

给定字母的二进制编码,求构造出二进制串s的二进制编码有几种不同的方法。

solution:

dp

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
int t,n,m;
string s;
int dp[500005];
int flag[500005];
string ss[30],ch[30];
bool check(int pos,int now)
{
   
    if(pos<ss[now].length()-1)return false;
    for(int i=0;i<ss[now].length();i++)
        if(ss[now][i]!=s[pos+i-ss[now].length()+1])return false;
    return true;
}
int main()
{
   
    scanf("%d",&t);
    while(t--)
    {
   
        scanf("%d%d",&n,&m);
        for(int i=0;i<m;i++)
            cin>>ch[i]>>ss[i];
        for(int i=0;i<=n;i++)dp[i]=0,flag[i]=0;
        cin>>s;
        for(int i=0;i<n;i++)
        {
   
            for(int j=0;j<m;j++)
            {
   
                if(check(i,j))
                {
   
                    if(ss[j].length()-i==1)
                    {
   
                        dp[i]+=1;
                        if(flag[i]==0)
                            flag[i]=1;
                        else if(flag[i]==1)
                            flag[i]=2;
                    }
                    else if(ss[j].length()<=i)
                    {
   
                        dp[i]=(dp[i-ss[j].length()]+dp[i])%128;
                        if(flag[i-ss[j].length()]==1)
                        {
   
                            if(flag[i]==0)
                                flag[i]=1;
                            else if(flag[i]==1)
                                flag[i]=2;
                        }
                        else if(flag[i-ss[j].length()]==2)
                            flag[i]=2;
                    }
                }
            }
        }
        if(flag[n-1]==0)
            printf("nonono\n");
        else if(flag[n-1]==1)
            printf("happymorsecode\n");
        else
            printf("puppymousecat %d\n",dp[n-1]);
    }
    return 0;
}

I-Intersections

题意:

给定能向左向右走的条件,以及花费,向上向下走的条件,以及花费。求从起点到终点的最短距离。

solution:

另类最短路Dijktra()

#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f3f3f3f3f
typedef long long ll;
typedef pair<int,int>P;
int n,m,sx,sy,tx,ty;
int a[505][505];
int b[505][505];
int c[505][505];
int w[505][505];
ll t[505][505];
int dx[]={
   1,-1,0,0},dy[]={
   0,0,1,-1};
struct node
{
   
    int x,y;
    ll t;
    bool operator>(const node p)const
    {
   
        return t>p.t;
    }
};
void dijktra()
{
   
    memset(t,INF,sizeof(t));
    t[sx][sy]=0;
    priority_queue<node,vector<node>,greater<node>>que;
    que.push(node{
   sx,sy,t[sx][sy]});
    while(!que.empty())
    {
   
        node p=que.top();que.pop();
        if(p.t%(a[p.x][p.y]+b[p.x][p.y])<a[p.x][p.y])
        {
   
            for(int i=0;i<2;i++)
            {
   
                int x=p.x+dx[i],y=p.y+dy[i];
                if(x<0||x>=n||y<0||y>=m)continue;
                ll tt=p.t;
                if(i==0)
                    tt+=w[p.x][p.y];
                else
                    tt+=w[x][y];
                if(tt>=t[x][y])continue;
                t[x][y]=tt;
                que.push(node{
   x,y,tt});
            }
        }
        else
        {
   
            ll tem=a[p.x][p.y]+b[p.x][p.y]-(p.t%(a[p.x][p.y]+b[p.x][p.y]));
            for(int i=0;i<2;i++)
            {
   
                int x=p.x+dx[i],y=p.y+dy[i];
                if(x<0||x>=n||y<0||y>=m)continue;
                ll tt=p.t+tem;
                if(i==0)
                    tt+=w[p.x][p.y];
                else
                    tt+=w[x][y];
                if(tt>=t[x][y])continue;
                t[x][y]=tt;
                que.push(node{
   x,y,tt});
            }
        }
        if(p.t%(a[p.x][p.y]+b[p.x][p.y])!=0&&p.t%(a[p.x][p.y]+b[p.x][p.y])>=a[p.x][p.y])
        {
   
            for(int i=2;i<4;i++)
            {
   
                int x=p.x+dx[i],y=p.y+dy[i];
                if(x<0||x>=n||y<0||y>=m)continue;
                ll tt=p.t;
                if(i==2)
                    tt+=c[p.x][p.y];
                else
                    tt+=c[x][y];
                if(tt>=t[x][y])continue;
                t[x][y]=tt;
                que.push(node{
   x,y,tt});
            }
        }
        else
        {
   
            ll tem=0;
            if(p.t%(a[p.x][p.y]+b[p.x][p.y])==0)
                tem=a[p.x][p.y];
            else
                tem=a[p.x][p.y]-p.t%(a[p.x][p.y]+b[p.x][p.y]);
            for(int i=2;i<4;i++)
            {
   
                int x=p.x+dx[i],y=p.y+dy[i];
                if(x<0||x>=n||y<0||y>=m)continue;
                ll tt=p.t+tem;
                if(i==2)
                    tt+=c[p.x][p.y];
                else
                    tt+=c[x][y];
                if(tt>=t[x][y])continue;
                t[x][y]=tt;
                que.push(node{
   x,y,tt});
            }
        }
    }

}
int main()
{
   
    scanf("%d%d%d%d%d%d",&n,&m,&sx,&sy,&tx,&ty);
    sx--;sy--;tx--;ty--;
    for(int i=0;i<n;i++)
        for(int j=0;j<m;j++)
        scanf("%d",&a[i][j]);
    for(int i=0;i<n;i++)
        for(int j=0;j<m;j++)
        scanf("%d",&b[i][j]);
    for(int i=0;i<n;i++)
        for(int j=0;j<m-1;j++)
        scanf("%d",&c[i][j]);
    for(int i=0;i<n-1;i++)
        for(int j=0;j<m;j++)
        scanf("%d",&w[i][j]);
    dijktra();
    printf("%lld",t[tx][ty]);
    return 0;
}

J-Just Multiplicative Inverse

题意:

求操作次数的期望。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
int t;
ll vis[1000005];
int main()
{
   
    scanf("%d",&t);
    vis[0]=vis[1]=1;
    while(t--)
    {
   
       int p;scanf("%d",&p);
       ll res=1;
       for(int i=2;i<p;i++)
       {
   
           vis[i]=vis[p%i]+1;
           res=res+vis[i];
       }
       printf("%.9f\n",res*1.0/(p-1));
    }
    return 0;
}

K-Kanade Hates Recruitment

L-Leave from CPC