2021“MINIEYE杯”中国大学生算法设计超级联赛第二场补题

1012(签到)

题意:判断字符串中是否含有"114514"序列,有的话输出“AAAAAA”,没有的话输出“Abuchulaile”。

代码:

#include <iostream>
#include <string>
using namespace std;

int T;
string s,x;

int main(){
    int flag=0;
    cin>>T;
    x="114514";
    while(T--){
        flag=0;
        cin>>s;
        if(s.find(x)!=string::npos){
            cout<<"AAAAAA";
        }else{
            cout<<"Abuchulaile";
            
        }cout<<endl;
    }
    return 0;
}

1001:

题目大意:判断边长为n的顶点中有多少个等边三角形,且三角形的边平行于xoy,yoz或xoz平面;

解题思路: 

观察发现三个点所有坐标都是整数的三角形只可能是第二个样例的那八种情况,即类似(0, 0, 0), (1, 0, 1), (0, 1, 1)。证明的话正三角形一条边平行于棱的情况很容易发现是不成立的。

这样就只需要知道边长为n - 1的立方体包含多少边长为1,2...n-1的立方体,再将答案乘以8即可。

Σn−1i=18×i3=2(n(n−1))2Σi=1n−18×i3=2(n(n−1))2。n-1必须要先模一下模数!

代码:

#include <bits/stdc++.h>
#define mod 1000000007
#define int __int128
using namespace std;

//读入 
inline __int128 read()
{
   int X=0,w=0; char ch=0;
   while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
   while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
   return w?-X:X;
}
//输出  以字符串形式进行输出  避免越界导致结果都一样 
void print(__int128 x)
{
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    if(x>9)print(x/10);
    putchar(x%10+'0');
}
signed main() {
	signed t;
	cin >> t;
	while(t--) {
		int n;
		n = read();
		//边平行于棱的肯定没有
		if(n == 0 || n == 1) {
			cout << 0 << endl;
			continue;
		}
		n--;
		//cout << (1 + n) * n / 2 * 8 << endl;
		n %= mod;
		print((1 + n) * n % mod * (1 + n) % mod * n % mod * 2 % mod);
		cout << endl;
	}
	return 0;
}

1005:

题目大意:对于一个字符串,我们要进行n次操作。对于每个操作,可以在当前字符串之前或之后插入操作序列的下一个字符。最后一个字符串的字典顺序越小,最后的分数就越高。

解题思路:仔细分析可以得到,对于特定的字符而言,使得字典序最小的顺序是固定的,只有对于前面相同的前缀。,所以只需要计算相同前缀字符的个数n,求出对应的2^(k-1)输出即可。

代码:

#include<bits/stdc++.h>
using namespace std;
const int mo=1e9+7;
int ksm(int x,int y)
{
    int ret=1;
    while (y)
    {
        if (y&1) ret=1ll*ret*x%mo;
        x=1ll*x*x%mo;
        y=y>>1;
    }
    return ret;
}
int main()
{
    int t;
    scanf("%d",&t);
    while (t)
    {
        t--;
        int n;
        scanf("%d",&n);//字符串长度 
        char s[200020];
        scanf("%s",s+1);
        int ll=0;
        for (int i=1;i<n;i++) if (s[i]!=s[i+1])
        {
            ll=i;
            break;
        }
        if (!ll) ll=n;
        printf("%d\n",ksm(2,ll-1));
    }
}

 1008:

 

 题目大意:有n个考试科目,现在有m套复习资料,每套复习资料需要花费wi天使用,用完提升ci的分数,现在还有t天复习时间,挂科数目不能超过p,问所有可以达到的最大分数。

解题思路:首先01背包求出每门课花费k天可以最多得到多少分,然后dp[i][k][l]前i门课程,复习了k天,挂了l门课程的最大分数。利用状态转移方程dp[i][k][l]=max(dp[i-1][k-j][l-x]+f[j],dp[i][k][l])计算得到结果。

代码:

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

const int inf=0x3f3f3f3f;
int n,m;

map<string,int>mp;
string s;
int f[3000],dp[60][3000][15];

struct node
{
    int x,y;
};
vector<node>vec[500];  
int main()
{
    int t;
    scanf("%d",&t);//一共几组测试样例 
    while(t--)
    {	
    	//n个考试科目 
        scanf("%d",&n);
        string s;
        for(int i=1; i<=n; i++)
        {
            cin>>s;
            mp[s]=i;
        }
        
        //m套复习资料 
        scanf("%d",&m);
        for(int i=0; i<m; i++)
        {
            string s;
            int x,y;
            //名字  收益  付出   
            cin>>s>>x>>y;
            int id=mp[s];//map与vector将课程收益 付出联系起来 
            vec[id].push_back(node{x,y});
        }
        //复习天数  失败上限 
        int d,p;
        scanf("%d %d",&d,&p);
        memset(dp,-0x3f,sizeof(dp));
        dp[0][0][0]=0;//初始化 边界 
        
        for(int i=1; i<=n; i++)
        {
            memset(f,-inf,sizeof f);
            f[0]=0;
            
            //01背包求出每门课花费k天可以最多得到多少分。
            for(int j=0; j<vec[i].size(); j++)
            {
                for(int k=d; k>=vec[i][j].y; k--)
                {
                    f[k]=max(f[k],f[k-vec[i][j].y]+vec[i][j].x);
                }
            }
			
            for(int j=1;j<=d;j++)
            {
                for(int k=j;k<=d;k++)
                {
                    for(int l=0;l<=p;l++)
                    {
                        if(f[j]<0) continue;	//没有复习资料 
                        bool x=0;				//初始化 
                        if(f[j]<60) x=1;		//最大也无法大于60分  挂科 
                        if(f[j]>100) f[j]=100;
                        if(l>=x)				//还未到达挂科最大数目 
                        {
                            dp[i][k][l]=max(dp[i-1][k-j][l-x]+f[j],dp[i][k][l]);
							//前i门课程,复习了k天,挂了l门课程的最大分数。
                        }
                    }
                }
            }
        }
        //遍历 得到最大值 
        int mx=-inf;
        for(int i=0;i<=d;i++)
        {
            for(int j=0;j<=p;j++)
            {
                mx=max(mx,dp[n][i][j]);
            }
        }
        if(mx<0)  cout<<"-1"<<endl;
        else cout<<mx<<endl;
        //为下一次循环做准备 
        mp.clear();
        for(int i=1;i<=n;i++)
        {
            vec[i].clear();
        }
    }
   return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值