2020年“美团杯”程序设计挑战赛 部分题解

http://uoj.ac/contest/53/standings

签了一个A,然后就就结束了。全靠队友,又会玩魔塔,又会matlab又会猜原根。。。。

A查查查乐乐

div2 C题难度的DP,去年银川网络赛第二场抄的很久以前的cf的原题

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxl=210+10;

int n,cas,ans;
int dp[maxl][6];
char s[maxl],a[6]; 

inline void prework()
{
	scanf("%s",s+1);
	n=strlen(s+1);
	a[1]=a[2]=a[3]='x';
	a[4]=a[5]='l';
}

inline void mainwork()
{
	for(int i=0;i<=n;i++)
		for(int j=0;j<=5;j++)
			dp[i][j]=101;
	dp[0][0]=0;
	for(int i=1;i<=n;i++)
	if(s[i]=='x')
	{
		dp[i][0]=dp[i-1][0]+1;
		dp[i][1]=min(dp[i-1][0],dp[i-1][1]+1);
		dp[i][2]=min(dp[i-1][1],dp[i-1][2]+1);
		dp[i][3]=min(dp[i-1][2],dp[i-1][3]);
		dp[i][4]=dp[i-1][4];
	}
	else
	{
		dp[i][0]=dp[i-1][0];
		dp[i][1]=dp[i-1][1];
		dp[i][2]=dp[i-1][2];
		dp[i][3]=dp[i-1][3]+1;
		dp[i][4]=min(dp[i-1][3],dp[i-1][4]+1);
	}
	ans=101;
	for(int i=0;i<=4;i++)
		ans=min(dp[n][i],ans);
}

inline void print()
{
	printf("%d\n",ans);
}

int main()
{
	int t;
	scanf("%d",&t);
	for(cas=1;cas<=t;cas++)
	{
		prework();
		mainwork();
		print();
	}
	return 0;
}

 

 

B图片解密

数学院的队友会用matlab,然而我啥可视化都不会。。。

set1直接10不同色缩小就好了

set2

通过新加坡那个钟,

发现86400=24*60*60,然后就只要看时针和分针组成的图案就行了

 

 

C魔塔

队友玩出来了。。我玩了一个小时没玩出来。。。一开始发现第一个问号钥匙颜色总是一样的,以为问号颜色不变。。。标了张表格后发现有一些问号颜色会变。。。吐了

 

 

E半前缀计数

队友说“这题区域赛金牌起步的sam,然而在这里被当签到题20分钟就被人切了”

#include<bits/stdc++.h>
using namespace std;
const int N=2e6+10;
int T[N][30],fa[N],len[N],cnt,last,pos[N];
void build(int v){
    int i,p=last,np,q,nq;
    last=np=++cnt;
    len[np]=len[p]+1;
    for(;p&&T[p][v]==0;p=fa[p]) T[p][v]=np;
    if(p==0) fa[np]=1;
    else{
        q=T[p][v];
        if(len[q]==len[p]+1) fa[np]=q;
        else{
            nq=++cnt;
            len[nq]=len[p]+1;
            fa[nq]=fa[q];
            fa[q]=fa[np]=nq;
            for(i=0;i<27;i++) T[nq][i]=T[q][i];
            for(;T[p][v]==q;p=fa[p]) T[p][v]=nq;
        }
    }
}

char s[1000010];
long long sum[1000010][30];
vector<int>g[N];
void dfs(int u,int f){
     int i,v;
     for(i=0;i<g[u].size();i++){
         v=g[u][i];
         if(v!=f){
             dfs(v,u);
             pos[u]=max(pos[v],pos[u]);
         }
     }
}


int main(){
    long long l,r,f,i,j,n,a,b;
    scanf("%s",s+1);
    n=strlen(s+1);
    last=cnt=1;
    for(i=1;i<=n;i++){
        build(s[i]-'a');
        pos[last]=i;

        for(j=0;j<=26;j++) sum[i][j]=sum[i-1][j];
        sum[i][s[i]-'a']++;
    }

    for(i=1;i<=cnt;i++) g[fa[i]].push_back(i);
    dfs(1,0);

    long long ans=0;
    for(i=2;i<=cnt;i++){
        l=pos[i]-len[i]+1;
        r=pos[i]-len[fa[i]];
        a=l;
        b=len[i]-len[fa[i]];
        ans+=(a+a+b-1)*b/2;  //?

        for(j=0;j<=26;j++){
            a=sum[r][j]-sum[l-1][j];
            if(a==0) continue;
            b=sum[l-1][j];

            if(s[r]-'a'==j){
                ans-=(b+b+a)*(a-1)/2;
                if(fa[i]!=1) ans-=a+b;
            }
            else ans-=(b+1+b+a)*a/2;
        }
    }
    cout<<ans+1<<endl;

}

 

G平行四边形

队友说这是个质数应该要用到原根,然后突然就过了?(流下了不会数学的泪水)

#include<bits/stdc++.h>
using namespace std;
bool ck(int x,int mod){
	int ans=x*x%mod,k=2;
	while(ans!=1)ans=ans*x%mod,k++;
	return k==mod-1;
}
int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		int n;
		scanf("%d",&n);
		int p=n+1,g=0;
		for(int i=2;i<p;i++){
			if(ck(i,p)){
				g=i;
				break;
			}
		}
		if(g==0){printf("-1\n");break;}
		int j=1;
		for(int i=1;i<p;i++){
			printf("%d %d\n",i,j);
			j=j*g%p;
		}
	}
} 

M最长公共子序列

这题先把1放在中间,然后维护一个从前到后的顺序,然后二分去确定每一个进来的数应该放在哪一个前面

每次询问就A[0]=i,A[1]=a[mid],如果a[mid]在i后面,则get_lcs=2,否则=1

刚好100*log约等于65

#include "lcs.h"
#include<bits/stdc++.h>
using namespace std;
void find_permutation(int n, int res[])
{
	vector<int>k;
	int A[3];
	k.push_back(1);
	int l=0,r=0,mid=0;
	for(int i=2;i<=n;i++){
		l=0,r=k.size()-1;
		while(l<=r){
			mid=l+r>>1;
			A[0]=k[mid],A[1]=i;		
			if(get_lcs(2,A)==1)r=mid-1;
			else l=mid+1;
		}
		if(l>mid)k.insert(k.begin()+mid+1,i);
		else k.insert(k.begin()+mid,i);
	}
	for(int i=0;i<n;i++)res[i]=k[i];
}

 

N热身题

我数独也不会玩,太菜了,还好队友前一天晚上玩出来了

7 1 3 4 8 6 2 9 5
2 4 9 3 5 7 8 6 1
8 5 6 2 1 9 4 7 3
6 7 5 9 4 8 1 3 2
4 2 8 7 3 1 9 5 6
3 9 1 6 2 5 7 8 4
1 8 2 5 9 3 6 4 7
9 3 7 1 6 4 5 2 8
5 6 4 8 7 2 3 1 9

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值