• 【2020.12.02提高组模拟】球员(player) 题解


    题意描述

    基本的递推

    ①所有运动员姓氏的长度必须不同。

    ②每个运动员的姓氏必须是长度比其长的所有其他运动员姓氏的连续子串

    潜在的球员分成 N
    类,第i类的球员的姓氏恰好有i个字母,且每一类恰好有K个球员。 有多少种不同的方法选出满足要求的N个球员。答案对109+7取余。

    Solution

    看上去是字符串匹配,其实长度只差1,只用把更长的字符串砍掉最前面一个或者最后面一个然后直接比较是否相同即可,如果它长度是len-1的前缀和后缀相同,只要递推一次,注意map是不可重的,最后累加答案的时候不能加几次

    substr是切割函数,s.substr(x,y)是从一个string里切除从x到y的字符串,若y==s.size()可省略

    string输入用scanf两行泪

    #include<bits/stdc++.h>
    #define max(a,b) (a>b?a:b)
    #define min(a,b) (a<b?a:b)
    #define ll long long
    #define re register
    #define inf 0x3f3f3f3f
    using namespace std;
    int  mod=1000000007;
    const int N=53;
    int n,k;
    string s[N][1503],t1,t2;
    int i,j,kk;
    ll ans;
    map<string,ll> m;
    template <class T> inline void read(T &x){
    	x=0;int g=1; char s=getchar();
    	for (;s>'9'||s<'0';s=getchar())	if (s=='-') g=-1;
    	for (;s<='9'&&s>='0';s=getchar()) x=(x<<1)+(x<<3)+(s^48);
    	x*=g;
    }
    signed main()
    {
    	freopen("player.in","r",stdin);freopen("player.out","w",stdout);
    	read(n);read(k);
    	for (i=1;i<=n;i++)
    		for (j=1;j<=k;j++)
    			cin>>s[i][j];	
    	for (i=1;i<=k;i++) m[s[1][i]]++;
    	for (i=2;i<=n;i++)
    	{
    		for (j=1;j<=k;j++)
    		{
    			t1=s[i][j].substr(0,s[i][j].size()-1);
    			t2=s[i][j].substr(1);
    			if (m.find(t1)!=m.end())
    			m[s[i][j]]=(m[t1]+m[s[i][j]])%mod;
    			if (m.find(t2)!=m.end())
    			if (t1!=t2)
    			m[s[i][j]]=(m[t2]+m[s[i][j]])%mod;
    		}
    	}
    	for (i=1;i<=k;i++) ans=(ans+m[s[n][i]])%mod,m[s[n][i]]=0;
    	printf("%lld",ans);
    	return 0;
    }               
    

    详见hash大犇的博客

  • 相关阅读:
    Go module学习笔记
    java并发基础及原理
    java并发之内存模型
    https理论及实践
    Mysql查询结果导出Excel表
    mysql清空表数据并重置自增ID
    html a标签链接点击闪动问题解决
    rocketmq-console控制台管理界面配置
    nginx多层反代配置变量proxy_set_header
    nginx 实现浏览器文件下载服务
  • 原文地址:https://www.cnblogs.com/Ritalc/p/14075095.html
Copyright © 2020-2023  润新知