2017-2018 ACM-ICPC, Asia Daejeon Regional Contest 一些题解

D. Happy Number(solved by w222222s)
妥妥的水题,模拟一下就行了

#include 
#include 
using namespace std;
const int INF=0x3f3f3f3f;
const int MOD=1e9+7;
char s[20];
set <long long> st;
long long cal(long long n)
{
    long long ans=0;
    sprintf(s,"%lld",n);
    int len=strlen(s);
    for(int i=0;i<len;i++)
    {
        ans+=(s[i]-'0')*(s[i]-'0');
    }
    return ans;
}
int main()
{
    long long n;
    scanf("%lld",&n);
    long long ans=0;
    int flag=0;
    while(1)
    {
        if(n==1)
        {
            flag=1;
            break;
        }
        //cout<
        if(st.count(n))
            break;
        st.insert(n);
        n=cal(n);
    }
    if(flag)
        cout<<"HAPPY"<<endl;
    else
        cout<<"UNHAPPY"<<endl;
    return 0;
}

F. Philosopher’s Walk (solved by practer)
是个递归,首先根据大小将位置减少到8x8,然后用打好的表判断一下。

#include 
#include 
#include 
#include 
using namespace std;
typedef long long ll;
struct node
{
    int next[5];
    int w[5];
    node(){};
    node(int a,int b,int c,int d,int e,int f,int g,int h)
    {
        next[1]=a;
        next[2]=b;
        next[3]=c;
        next[4]=d;
        w[1]=e;
        w[2]=f;
        w[3]=g;
        w[4]=h;
    };
};
node z[10];
int main()
{
    z[1]=node(6,1,1,7,1,2,3,4);
    z[2]=node(8,2,2,5,4,3,2,1);
    z[3]=node(5,3,3,8,2,1,4,3);
    z[4]=node(7,4,4,6,3,4,1,2);

    z[6]=node(1,6,6,4,1,4,3,2);
    z[5]=node(3,5,5,2,2,3,4,1);
    z[7]=node(4,7,7,1,3,2,1,4);
    z[8]=node(2,8,8,3,4,1,2,3);
    long long  n,k;
    cin>>n>>k;
    int flag=1;
    long long  x=1,y=1;
    while(n>=2)
    {
        long long  tt=(n*n/4);
        int  t=(k/tt+(k%tt!=0));
       // cout<
        int cnt=z[flag].w[t];
        flag=z[flag].next[t];
        n/=2;
        if(cnt==1)
        {
            x=x;
            y=y;
        }
        else if(cnt==2)
        {
            x=x;
            y+=n;
        }
        else if(cnt==3)
        {
            x+=n;
            y+=n;
        }
        else
        {
            x+=n;
            y=y;
        }
        k%=(tt);
        if(k==0) k=tt;
       // cout<
    }
    cout<<x<<' '<<y<<endl;
    return 0;
}

C - Game Map (solved by limn2o4)
题目赤裸裸的暗示了偏序关系,那就建图呗。
首先用利用原图的度数信息,建立从度数小的点到相邻度数大的节点的有向边,再有向图上求最长路,只要用拓扑排序就行了

#include 
#define ll long long
using namespace std;
const int MAXN  = 1e5 +10;
const int MAXM = 3e5 +10;
const int INF = 0x3f3f3f3f;
vector<int> e[MAXN],edge[MAXN];
int dp[MAXN],d[MAXN];
void bfs(int n)
{
    for(int i = 1;i<=n;i++)
    {
        dp[i] = 1;
    }
    queue<int> q;
    for(int i  =1;i<=n;i++)
    {
        if(d[i] == 0) q.push(i);
    }
    while(!q.empty())
    {
        int u = q.front();
        q.pop();
        for(auto v : edge[u])
        {
            d[v]--;
            if(d[v] == 0) q.push(v);
            dp[v] = max(dp[v],dp[u]+1);
        }
    }
    printf("%d\n",*max_element(dp+1,dp+1+n));
}
int deg[MAXN];
bool flag[MAXN];
int n,m;
int main()
{
    scanf("%d%d",&n,&m);
    for(int i = 0;i<m;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        u++,v++;
        e[u].push_back(v);
        e[v].push_back(u);
        deg[u]++,deg[v]++;
    }
    for(int i = 1;i<=n;i++)
    {
        for(auto v : e[i])
        {
            if(deg[i] < deg[v])
            {
                edge[i].push_back(v);
                d[v]++;
            }
        }
    }
    bfs(n);
    return 0;
}

I - Slot Machines (Upsolved by limn2o4)
赛后发现自己理解有偏差,感觉很难受。
实际上这种阅读理解题是比赛的一部分吧……、
其实是求从某个位置开始的循环节,加上前面不在循环节的部分的最小值。
序列反着读,KMP一下求个最小循环节就行了

#include 
#include 
#define ll long long
#define next fuck
using namespace std;
const int MAXN = 1e6 + 6;
const int INF = 0x3f3f3f3f;
void kmp_pre(int x[],int m,int next[])
{
    int i,j;
    j = next[0] = 0;
    i = 1;
    while(i<=m)
    {
        while(0!=j && x[i] != x[j]) j = next[j];
        next[++i] = ++j;
    }
}
int next[MAXN];
int x[MAXN];
int main()
{
    int n;
    scanf("%d",&n);
    for(int i = n;i>=1;i--)
    {
        scanf("%d",&x[i]);
    }
    kmp_pre(x,n,next);
    int ansp = INF,ansk = INF;
    for(int i = 1;i<=n;i++)
    {
        int np = i - next[i+1]+1,nk = n - i;
        if(np + nk < ansk + ansp)
        {
            ansp = np,ansk = nk;
        }
    }
    printf("%d %d\n",ansk,ansp);
    return 0;
}

你可能感兴趣的:(ACM,Contest)