现在的位置: 首页 > 综合 > 正文

HIT_Training_20140417

2019年02月20日 ⁄ 综合 ⁄ 共 3538字 ⁄ 字号 评论关闭

A题。算是个模拟。华丽丽的写了100行,代码能力还是不行。

B题。凸包加dp,不会。

C题。字符串,kmp。操作是能将字符串一分为二然后交换位置。操作的次数是无限的。

发现将这两个字符串分别首尾相接他两是一样的。。于是将b+=b;然后kmp跑a在b中的匹配。

D题。并查集。比赛的时候想到并查集了。但是退盟操作没有想到比较好的方法。

每次退盟的时候,可以给这个国家一个新的id,相当于新加了一个独立的点,可以默认为已经将这个点从原来的盟国中删除掉了。

#include<cstring>
#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<string>
#include<cstdlib>
#include<string>
#include<map>
using namespace std;
#define re freopen("in.txt","r",stdin)
#define we freopen("out.txt","w",stdout)
#define maxn 100100*10
#define maxm 200005
#define ll long long
#define ld long double



int fa[maxn];
int n;
int id[maxn];
void ini()
{
    for(int i=0; i<maxn; i++)
        fa[i]=i,id[i]=i;
}
int Fin(int a)
{
    if(fa[a]==a)return fa[a];
    fa[a]=Fin(fa[a]);
    return fa[a];
}
void Uni(int a,int b)
{
    a=Fin(a);
    b=Fin(b);
    if(a==b)return;
    fa[a]=b;
}
bool vis[maxn];
int main()
{
    int a,b;
   // re;
    int m;
    int nc=1;
    while(~scanf("%d%d",&n,&m)&&(n+m))
    {
        char s[11];
        ini();
        int tot=n;
        while(m--)
        {
            scanf("%s",s);
            if(s[0]=='M')
            {
                scanf("%d%d",&a,&b);
                Uni(id[a],id[b]);
            }
            else if(s[0]=='S')
            {
                scanf("%d",&a);
                id[a]=tot++;
            }
        }
        int ans=0;
        memset(vis,false,sizeof(vis));
        for(int i=0; i<n; i++)
        {
            int t=Fin(id[i]);
            if(!vis[t])vis[t]=true,ans++;
        }
        printf("Case #%d: %d\n",nc++,ans);
    }
    return 0;
}

E题。比较简单的DP。因为我会。。

有n个台阶,每一次可以跨x或者y个台阶。问必须经过a和b两个台阶的方案数有多少。

用dp[i]表示到第i个台阶的方案数。那么要求的答案就是dp[a]*dp[b-a]*dp[n-b];相当于分解为三段小去走。

WA一次因为没看题下面的mod10……07;

#include<cstring>
#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<string>
#include<cstdlib>
#include<string>
#include<map>
using namespace std;
#define re freopen("in.txt","r",stdin)
#define we freopen("out.txt","w",stdout)
#define maxn 10011
#define maxm maxn*maxn/2
#define ll long long
#define ld long double

#define mod 1000000007
ll dp[maxn];
int main()
{
    int nc;
    //re;
    int n;
    int x,y,a,b;
    while(5==scanf("%d%d%d%d%d",&n,&x,&y,&a,&b)){
        memset(dp,0,sizeof(dp));
        dp[0]=1;
        if(a>b)swap(a,b);
        for(int j=1;j<=n;j++){
            if(j-x>=0)
            dp[j]=(dp[j]+dp[j-x])%mod;
            if(j-y>=0&&x!=y)
            dp[j]=(dp[j-y]+dp[j])%mod;
        }
        printf("%lld\n",(dp[a]%mod*dp[b-a]%mod)%mod*dp[n-b]%mod);
    }
    return 0;
}

F题。树dp。以前一个树dp的题也没做过。看到之后就傻了。于是瞎搞。。一直超时。。记忆化搜索也不错。于是改改改改。但是连样例都过不了。

要回寝室了。于是交一发,结果都没看,想着就是回了寝室接着搞。。但是回去打开一看居然过了。。尼玛。逗我呢。

#include<cstring>
#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<string>
#include<cstdlib>
#include<string>
#include<map>
using namespace std;
#define re freopen("in.txt","r",stdin)
#define we freopen("out.txt","w",stdout)
#define maxn 200005
#define maxm 200005
#define ll long long
#define ld long double



struct pp
{
    int u,v;
    int tt[6];
    int next;
}edge[maxm];
int head[maxn];
int vis[maxn];
int cnt;
void add(int u,int v,int a,int b,int c,int d)
{
    edge[cnt].u=u;
    edge[cnt].v=v;
    edge[cnt].next=head[u];
    edge[cnt].tt[0]=a;
    edge[cnt].tt[1]=b;
    edge[cnt].tt[2]=c;
    edge[cnt].tt[3]=d;
    head[u]=cnt++;
}
int aa[maxn],bb[maxn];
int dp[maxn][2];
bool dvis[maxn][2];
int dfs(int n,int type)
{
    int sum=0;
    if(dvis[n][type])return dp[n][type];
    for(int i=head[n];~i;i=edge[i].next){
        int v=edge[i].v;
        if(vis[v])continue;
        if(type==0)
        sum+=min(dfs(v,1)+edge[i].tt[1]+bb[v],aa[v]+dfs(v,0)+edge[i].tt[0]);
        else
        sum+=min(dfs(v,1)+edge[i].tt[3]+bb[v],aa[v]+dfs(v,0)+edge[i].tt[2]);
    }
    dp[n][type]=sum;
    dvis[n][type]=1;
    return sum;
}
int main()
{
//    re;
    int nc;
    scanf("%d",&nc);
    while(nc--){
        int n;
        scanf("%d",&n);
        memset(head,-1,sizeof(head));
        cnt=0;
        memset(vis,false,sizeof(vis));
        memset(dvis,false,sizeof(dvis));
        for(int i=1;i<=n;i++)
            scanf("%d",&aa[i]);
        for(int i=1;i<=n;i++)
            scanf("%d",&bb[i]);
        int m=n-1;
        int a,b,c,d,e,f;
        while(m--){
            scanf("%d%d%d%d%d%d",&a,&b,&c,&d,&e,&f);
            add(a,b,c,d,e,f);
        }
        vis[1]=true;
        int ans=min(dfs(1,0)+aa[1],dfs(1,1)+bb[1]);
        printf("%d\n",ans);
    }
    return 0;
}

F、G不会。日后补充。

抱歉!评论已关闭.