2021“MINIEYE杯”中国大学生算法设计超级联赛(4)补题

 

    1001Calculus   

题目大意:多组测试,每组将输入一个式子,式子之间由加号连接,系数C的取值范围为0到1e9,式子中的每一项均来自给出的函数集合当中,请你判断,所给式子的和函数是否收敛(当x趋向于正无穷的时候,式子趋向于一个稳定的值)。

题目链接:Problem - 6985 (hdu.edu.cn)

输入样例:

2

1sinx+0cosx+3x+6/sinx 0

0

输出样例:

NO

YES

解题思路:很容易可以想到,只有当式子中每一项均为0的时候,和函数才能够收敛,所以,我们可以检验每一项的系数,只要有一项系数不为0,结果就是NO,查找的时候,第一项可以做个特判,后面的每个系数一定都是跟在加号后面的,我们只需要查找加号即可。

代码:

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

string s,str1,str2;
int s1,s2;
int main(){
	int t;
	cin>>t;
	str1="+";
	while(t--){
		cin>>s;
		int flag=0;//标记答案
		s1=0;
		if(s[s1]!='0')flag=1;//对第一项的系数进行特判断
		s1=s.find(str1);
		while(s1!=string::npos){//利用STL找到+的位置,判断加号后面的系数问题
			if(s[s1+1]!='0'){
				flag=1;
				break;
			}else s1=s.find(str1,s1+1);
		}
		if(flag==0)cout<<"YES"<<endl;
		else cout<<"NO"<<endl;
	}
	return 0;
}

1009)License Plate Recognition

题目大意:多组测试,每组给出一个30×100的字符数组,#表示图案,是一个车牌号,你需要找到车牌号每一位的左右边界并将其输出。

eg:

汉字:https://paste.ubuntu.com/p/B5pTWv7s6J/

车牌:https://paste.ubuntu.com/p/59bjvwY3Yr/

样例:

解题思路:总的思路比较简单,直接暴力扫描即可,但是有几个需要注意的点,第一个是汉字里面的川和鄂两个字并不是连着的,因此需要特判。还有最后一个数字的边界可能在最后一列,应判断下,代码是否能扫描到最后一列。

代码:

 #include <bits/stdc++.h>
 using namespace std;
 int t,d;
 char s[40][110];
 
 void init(){
     for(int i=1;i<=30;i++){
         for(int j=1;j<=100;j++){
             cin>>s[i][j];
         }
     }
 }
 
 //
 int c(int k){
     for(int i=1;i<=30;i++){
         if(s[i][k]=='#')return 1;
     }
     return 0;
 }
 
 int work(int left,int right){
     if(left==0||right==0)return 0;
     if(d==0&&right-left<=9)return 0;
     cout<<left<<" "<<right<<endl;
     return 1;
 }
 
 int main(){
     cin>>t;
     int tap=1;
     while(t--){
         init();
         cout<<"Case #"<<tap<<":"<<endl;
         tap++;
         d=0;
         int left=0,right=0,ll=1;
         while(ll<=100){
             if(c(ll)==0||ll==100){
                 //if(ll==100&&c(ll)==0)right=99;
                 if(ll==100&&c(ll)==1)right=100;
                if(work(left,right)==1){
                    left=0;
                    right=0;
                    d++;
                }
             }else{
                 if(left==0)left=ll;
                 else right=ll;
             }
             ll++;
        }
     }
     return 0;
 }


题目链接:Problem - 6986 (hdu.edu.cn)

题目大意:给出一个拥有n个节点与n-1条边的树,树的每个节点处都拥有一个编号代表了这个节点元素的种类,给出两个点u,v求出这两个节点之间最短路径上的元素种类,并且根据题意按照指定格式进行输出。

代码来自:【HDU6986】【2021杭电暑假多校】第四场1002 Kanade Loves Maze Designing_Akari Kitō的博客-CSDN博客

解题思路:要解决的核心问题就是得到任意两个点之间的元素种类,我们可以采用dfs来进行搜索,对每一个点都进行一次搜索,由于要计算的是元素的种类,需要对代码做出适当的调整。

颜色统计代码:

//标记是否判断,计数
void add(int x)
{
    if(!cnt[x]) sum++;
    ++cnt[x]; return ;
}
//对应add,删除标记,用于回溯
void del(int x)
{
    if(cnt[x] == 1) sum--;
    --cnt[x]; return ;
}
//标记  一一遍历  回溯
void dfs(int now, int la)
{
    add(c[now]); p[now] = sum;
    for(int i = 0; i < g[now].size(); ++i)
    {
        if(g[now][i] != la) dfs(g[now][i], now);
    }
    del(c[now]);
    return ;
}

 累加取模代码:(减法加快速度)

void fadd1(int &x, int y) {x += y; if(x >= mod1) x -= mod1; return ; }
void fadd2(int &x, int y) {x += y; if(x >= mod2) x -= mod2; return ; }

int ans1 = 0, ans2 = 0;
//按照题意对结果进行处理
for(int j = 1; j <= n; ++j)
{
    fadd1(ans1, 1ll * p[j] * bas1[j - 1] % mod1);
    fadd2(ans2, 1ll * p[j] * bas2[j - 1] % mod2);
}
printf("%d %d\n", ans1, ans2);

完整代码:

#include <bits/stdc++.h>
using namespace std;
vector<int> g[2005];
int t, n;
int c[2005], p[2005], cnt[2005], bas1[2005], bas2[2005];
int sum;
const int mod1 = (int)1e9 + 7;
const int mod2 = (int)1e9 + 9;

void Init()
{
    bas1[0] = bas2[0] = 1;
    for(int i = 1; i <= 2000; ++i)
    {
        bas1[i] = 1ll * bas1[i - 1] * 19560929 % mod1;
        bas2[i] = 1ll * bas2[i - 1] * 19560929 % mod2;
    }
    return ;
}
//标记 
void add(int x)
{
    if(!cnt[x]) sum++;
    ++cnt[x]; return ;
}
//删除标记 
void del(int x)
{
    if(cnt[x] == 1) sum--;
    --cnt[x]; return ;
}
//标记  一一遍历   回溯 
void dfs(int now, int la)
{	
	//计入元素种类 
    add(c[now]); 
	p[now] = sum;
    for(int i = 0; i < g[now].size(); ++i)
    {	
    	//搜索下一个点 
        if(g[now][i] != la) dfs(g[now][i], now);
    }
    //回朔 
    del(c[now]);
    return ;
}

void fadd1(int &x, int y) {x += y; if(x >= mod1) x -= mod1; return ; }
void fadd2(int &x, int y) {x += y; if(x >= mod2) x -= mod2; return ; }

int main(){
	//初始化 
    Init();
    scanf("%d", &t);    
    while(t--)
    {
        scanf("%d", &n);
        //输入图 
        for(int i = 2, x; i <= n; ++i)
        {
            scanf("%d", &x);
            //无向图    双向赋值 
            g[x].push_back(i); g[i].push_back(x);
        }
        //输入种类 
        for(int i = 1; i <= n; ++i) scanf("%d", &c[i]);
        for(int i = 1; i <= n; ++i)
        {
            dfs(i, -1);//对每个点进行深搜 
            int ans1 = 0, ans2 = 0;
            //对答案进行处理 
            for(int j = 1; j <= n; ++j)
            {
                fadd1(ans1, 1ll * p[j] * bas1[j - 1] % mod1);
                fadd2(ans2, 1ll * p[j] * bas2[j - 1] % mod2);
            }
            printf("%d %d\n", ans1, ans2);
        }
        //初始化 
        for(int i = 1; i <= n; ++i) g[i].clear();
    }
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值