码迷,mamicode.com
首页 > 其他好文 > 详细

2019CCPC秦皇岛赛区

时间:2020-02-17 12:19:39      阅读:187      评论:0      收藏:0      [点我收藏+]

标签:ram   acm   小数   line   存在   typedef   char s   str   space   

Link

Solutions


F. Forest Program

题意:

思路:
dfs+栈 判环
设图中环的大小分别为 \(c_1\) \(c_2\), ..., \(c_k\),不属于任何一个环的边数为 \(b\),则答案为:
\(2^b*\prod _{i=1}^{k}{(2^{c_i}-1)}\)
dfs 判环时 各点入栈 若点已存在于栈中 则存在环 计算环大小即可 不必出栈
跑一遍连通图即可计算出所有环
代码:


[View Code]

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=3e6+5;
const int mod=998244353;
vector<int>edge[maxn];
int vis[maxn],ins[maxn],s[maxn];
int top;
int n,m;
ll ans;
void init()
{
    ans=1;
    memset(vis,0,sizeof vis);
    memset(ins,0,sizeof ins);
    for(int i=1;i<=n;i++) edge[i].clear();
    top=0;
}
ll qPow(ll n,int a)
{
    ll res=1;
    while(a)
    {
        if(a&1) res=res*n%mod;
        n=n*n%mod;
        a>>=1;
    }
    return res;
}
void dfs(int u,int pre)
{
    s[++top]=u;
    ins[u]=1;
    vis[u]=1;
    for(auto x:edge[u])
    {
        if(!vis[x]) dfs(x,u);
        else if(ins[x]&&x!=pre)
        {
            int t=top;
            int sum=1;
            while(s[t]!=x)
            {
                t--;
                sum++;
            }
            m-=sum;
            ans=ans*(qPow(2,sum)-1+mod)%mod;
        }
    }
    ins[s[top]]=0;
    top--;
}
int main()
{
    int a,b;
    while(~scanf("%d%d",&n,&m))
    {
        init();
        for(int i=0;i<m;i++)
        {
            scanf("%d%d",&a,&b);
            edge[a].push_back(b);
            edge[b].push_back(a);
        } 
        for(int i=1;i<=n;i++)
            if(!vis[i])
                dfs(i,i);
        printf("%lld\n",ans*qPow(2,m)%mod);
    }
    return 0;
}

I. Invoker

题意:

思路:
dp
一个 special skill 最多有 \(6\) 种排列
将前后两个技能进行 \(36\) 种排列配对
\(dp[i][j]\)( \(i\) 为第 \(i\) 个技能, \(j\) 为技能 \(i\) 的第 \(j\) 种排列)
\(dp[i][j]=min(dp[i][j],dp[i-1][k]+cmp(s[i-1]_{k},s[i]_j)(0\le j,k\le 5))\)
代码:


[View Code]

#include<bits/stdc++.h>
using namespace std;
char s[100001]; 
map<char,int>mp;
char p[10][6][4]={ 
                    "QWE","QEW","WQE","WEQ","EQW","EWQ",
                    "WWW","WWW","WWW","WWW","WWW","WWW",
                    "WEE","WEE","EWE","EEW","EWE","EEW",
                    "QEE","QEE","EQE","EEQ","EQE","EEQ",
                    "QQE","QEQ","QQE","QEQ","EQQ","EQQ",
                    "EEE","EEE","EEE","EEE","EEE","EEE",
                    "QQW","QWQ","QQW","QWQ","WQQ","WQQ",
                    "QWW","QWW","WQW","WWQ","WQW","WWQ",
                    "QQQ","QQQ","QQQ","QQQ","QQQ","QQQ",
                    "WWE","WEW","WWE","WEW","EWW","EWW",
                  };
int dp[100001][6];
int cmp(int a,int b,int c,int d)
{
    if(!strcmp(p[a][b],p[c][d])) return 0;
    else if(p[a][b][1]==p[c][d][0]&&p[a][b][2]==p[c][d][1]) return 1;
    else if(p[a][b][2]==p[c][d][0]) return 2;
    return 3;
}
int main()
{
    mp['B']=0,mp['C']=1,mp['D']=2,mp['F']=3,mp['G']=4,mp['T']=5,mp['V']=6,mp['X']=7,mp['Y']=8,mp['Z']=9;    
    while(~scanf("%s",s))
    {
        for(int i=0;s[i];i++)
            for(int j=0;j<6;j++)
                dp[i][j]=(i+1)*3+i+1;
        for(int i=0;i<6;i++) dp[0][i]=3;
        for(int i=1;s[i];i++)
            for(int j=0;j<6;j++)
                for(int k=0;k<6;k++)
                    dp[i][j]=min(dp[i][j],dp[i-1][k]+cmp(mp[s[i-1]],k,mp[s[i]],j));
        int minn=0x3f3f3f3f;
        for(int i=0;i<6;i++) minn=min(minn,dp[strlen(s)-1][i]); 
        printf("%d\n",minn+strlen(s));
    }    
    return 0;
}

J. MUV LUV EXTRA

题意:

思路:
kmp
求小数部分后 \(k\) 位的真前后缀 倒着 kmp 就好
代码:


[View Code]

#include<bits/stdc++.h>
 
using namespace std;
 
typedef long long ll;
 
const int N=1e7+5;
 
char s[N];
ll nxt[N];
int len;
 
void getNext()
{
    int i=0;
    int j=-1;
    nxt[0]=-1;
    while(i<len)
    {
        if(j==-1||s[i]==s[j])
        {
            i++,j++;
            nxt[i]=j;
        }
        else j=nxt[j];
    }
}
int main()
{
    int a,b;
    while(~scanf("%lld%lld",&a,&b))
    {
        scanf("%s",s);
        sscanf(s,"%*[^.].%s",s);
        len=strlen(s);
        reverse(s,s+len);
        getNext();
        ll ans=a-b;
        for(ll i=2;i<=len;i++) ans=max(ans,a*i-b*(i-nxt[i]));
        printf("%lld\n",ans);
    } 
    return 0;
}

2019CCPC秦皇岛赛区

标签:ram   acm   小数   line   存在   typedef   char s   str   space   

原文地址:https://www.cnblogs.com/c4Lnn/p/12320955.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!