2019NYIST计科第七次周赛总结


秤取物体重量( 二进制枚举法)


nyoj动物统计(字符串操作)

Description 可以用字典树来写哟! 在美丽大兴安岭原始森林中存在数量繁多的物种,在勘察员带来的各种动物

资料中有未统计数量的原始动物的名单。科学家想判断这片森林中哪种动物 的数量最多,但是由于数据太过庞大,科学家终于忍受不了,想请聪明如你

的ACMer来帮忙。

Input 第一行输入动物名字的数量N(1<= N <=

1000),接下来的N行输入N个字符串表示动物的名字(字符串的长度不超过20,字符串全为小写字母,并且只有一组测试数据)。

Output 输出这些动物中最多的动物的名字与数量,并用空格隔开(数据保证最多的动物不会出现两种以上)。

Sample Input 1

10
boar
pig
sheep
gazelle
sheep
sheep
alpaca
alpaca
marmot
mole
Sample Output 1
sheep 3

思路如下:这一题的数据范围不是很大,我们可以用暴力的方法统计处各个动物出现的次数。为了偷懒我们可以用map容器去解决这个问提 我们把动物的名字的作为键,把出现的次数作为值,在循环输入的时候,用find函数其查找map中是否已经,有着这个动物,如果有 map的的值就加1,否则在map 添加 该动物的名字 并把值设为 1


题解如下

#include<iostream>
#include<string>
#include<map>
#include<algorithm>
#include<string.h> using namespace std;
/*
struct MyCmp {
bool operator()(string l, string r) const { return strcasecmp(l.c_str(), r.c_str()) < 0; }
};
*/ //一个自定义map 键 排序函数的范例!!!
int main()
{
int n;
cin>>n;
map<string,int,MyCmp> mp; //实例化map对象
for(int i = 0;i < n;i++)
{
string str;
cin>>str;
if(mp.find(str) == mp.end())
{
mp[str] = 1;
}
else
mp[str]++;
}
int max = 0; string st;
for(map<string,int,MyCmp>::iterator it = mp.begin();it != mp.end();it ++)
{
if(max < it->second)
{
max = it->second;
st = it->first;
}
}
cout<<st<<" "<<max<<endl;
return 0;
}

奥里给!

Description yzj学长听说学弟们觉得题太简单了,所以就出一个稍微有一丢丢难度的题来考考你们!

ACM工作室有n名队员和k个团队。每个队员都是某个团队的成员。所有团队的编号从1到k。现在你将获得一个编号t1、t2、…、tn的数组,其中ti是第i个员工的团队编号。

现在ACM工作室要集体去吃大餐,所以要租一辆容量为s的车,这个s可以任意的,但是容量为s的车最多只能上两个团队,如果上了三个团队,这三个团队将会因为yzj

学长打起来。由于我们是聪明的acmer,所以yzj学长想知道把所有团队都带到目的地的最小花费是多少?花费等于容量乘以乘车次数

注:

1:只能租一辆车

2:每次上车必须是一个团队一个团队的上,不能把一个团队的人拆开

Input

第一行包含两个整数n和k(1≤n≤5⋅10^5,1≤k≤8000)ACM工作室的队员数量和团队数量。第二行包含一个整数序列t1、t2、…、tn,其中ti(1≤ti≤k)是第i个队员的组号。每个团队至少包含一名队员。

Output 输出最小花费即可


思路如下:

这一题就是暴力求解,但是暴力也需要一点技巧,首先我们可以用一个for循环去 车的容量取值范围,然后再用两次嵌套循环,去求 对每一种 容量的车所需要的话费,求解

题解如下

#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std; const int LEN = 5e5 + 10;
int main()
{
int n,k;
cin>>n>>k;
int ar[8005] = {0};
int temp;
for(int i = 1;i <= n;i ++)
{
cin>>temp;
ar[temp]++;
}
sort(ar+1,ar+k+1,greater<int>());
int maxx = -1;
//获取 同时乘坐两个队伍需要的 最大容量maxx
for(int i = 1,j = k;i <= j;i++,j--)
{
if(i < j)
maxx = max(ar[i] + ar[j],maxx);
else
maxx = max(maxx,ar[i]);
}
//开始暴力枚举从容量为 ar[0]~maxx之间的所有情况(中间需经过 贪心优化同时乘坐的是那两个队伍) 耗费的话费,并最终找到最小花费
long long ans = 1e18; //存储当前情况的最小花费
for(long long int a = ar[1];a <= maxx;a++)
{
int times = 0,b = 1,c = k;
while(b <= c) //⚠️ 这里是 <= 符号 , 这个while循环表示 循环times次,就要 就要用车 运送 tiems次
{
times ++;
if(b < c&&(ar[b] + ar[c] <= a))
{
b++,c--;
}
else
{
b++;
}
}
ans = min(ans,times*a);
}
cout<<ans; return 0;
}

0和1

Description lsz喜欢二进制字符串(只包含’ 0’和’

1’的字符串)。而且他更喜欢“相等的二进制字符串”,其中‘0’和‘1’的数量是相等的。

lsz希望从原始字符串t中选择一个子字符串,使其成为长度尽可能最长的“相等的二进制字符串”。

lsz还希望从原始字符串t中选择一个子序列,使其成为长度尽可能最长的“相等的二进制字符串。

Input 第一行一个n(1<=n<100000),第二行是一个n长度的二进制字符串

Output 用空格分开的两个数

第一个是子串尽可能最长的“相等的二进制字符串”的长度,第二个是和子序列尽可能最长的“相等的二进制字符串”的长度

Sample Input 1

 8 01001001
Sample Output 1
4 6

Hint 为了防止有人不知道子串和子序列的区别,特意在这里提一下:

对于123456这个字符串

子串:必须在原字符串中是相邻的,比如它的子串有23、345、123456

子序列:在原序列中不必相邻,但是必须保证是原来的顺序,比如子序列有134、146

思路如下: 这一题我们可以把字符串中的0看作是1,1看作是-1,这样我们把前缀和加起来,当某一个未知的前缀和 与 之前某个位置的前缀和相同的时候两个未知之间的子序列0与1数量相同 或者 某个位置某个前缀和的值为0时则从开头为位置到当前位置的0与1的数量相同

题解如下:

#include<iostream>
#include<cmath>
using namespace std; const int LEN = 1e5+10;
int main()
{
int n;
cin>>n;
char ar[n];
cin>>ar;
int count_0=0,count_1=0;
int sum = 0; //求前缀和
int ans = 0;
int pre_sum[2*LEN] = {0}; //这个是用来存储,前缀最大和出现的情况,有点桶排的思想存储某种情况是否出现过
for(int i = 0;i < n;i ++)
{
if(ar[i] == '0') count_0++,sum+=1; //在这里我们默认 如果某一位是0 前缀和就+1,否则减1;
else count_1++,sum-=1; if(sum == 0) //如果sum的值为0,则前字符数组ar的前i个字符中 0与1的数量一定相同
{
if(ans < i)
ans = i;
continue;
}
if(pre_sum[sum+n] == 0) pre_sum[sum+n] = i; //我们 把得到的前缀和sum加上n 这样就不会出现下表为负值的情况,当该if语句成立的时候说明 这个sum值是第一次出现
//如果pre_sum[sum+n] == 0 说明这种情况还没有出现过,则我们就把 首次出现的这个前缀和 sum的位置存储起来
else if(i - pre_sum[sum+n] > ans) //否则这种情况前缀和sum已经出现过了,这个时候那这个前缀和的出现的位置 和 第一次的出现这个前缀和的位置 进行相减得到 0与1相同的一个连续字符串
ans = i - pre_sum[sum+n];
}
cout<<ans<<" "<<min(count_1,count_0)*2; return 0;
}

low || high

Description

p序列是一种整数序列p=[p1,p2,…,pn],这种序列包含n个在1到n之间的不同(唯一)的正整数。例如,下面的序列是p序列:[3,4,1,2],[1],[1,2]。以下序列不是p序列:[0],[1,2,1],[2,3],[0,1,2]。

你现在知道一个p序列的前缀最大值的数组q。

q1=p1, q2=max(p1,p2) q3=max(p1,p2,p3) … qn=max(p1,p2,…,pn)

问满足前缀最大值数组为q的p序列有多少种。(结果可能会很大,输出结果取余1000000007后的值)

Input 第一行包含整数t(1≤t≤10)——输入的测试用例的数量。

每个测试用例的第一行包含一个整数n(1≤n≤1e6)——数组q的长度。

测试用例的第二行包含n个整数q1,q2,…,qn(1≤qi≤n)——数组q的元素,保证所有qi≤qi+1(1<=i<n)

Output 每个测试样例输出一个数,表示满足前缀最大值数组为q的p序列的种数。(结果可能会很大,输出结果取余1000000007后的值)

Sample Input 1

4
5
1 2 3 4 5
5
2 3 4 4 5
5
3 3 5 5 5
5
2 2 2 5 5
Sample Output 1
1
1
4
0

思路如下: 根据前缀最大和的性质,一个数第一次出现的位置就是,它在原来的p序列的位置,而重复出现的位置则是,则是一定是比该重复数小的切还没有出现过的数字,因此我们可以从左到右遍历q序列,遇到第一次出现的,就将它填入p序列,遇到重复就选择一个比它小的填入p序列,根据 排列知识求出方案数。

题解如下:

#include<iostream>
using namespace std; #define max(a,b) (a>b?a:b)
const int mod = 1000000007;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
long long int ans = 1,sum = 0,now,befor = 0; //befor表示前一次输入的值,刚开始给befor不可能去到的值
for(int i = 1;i <= n;i ++)
{
scanf("%lld",&now);
if(now > befor) //条件成立则说明该值now 与前一个值befor不同,直接放入p序列
sum += now - befor -1; //统计这是 在这之前有多少个没有出现过的数字
else
{
ans = (ans * sum--) % mod; //如果相同则从sum个数字中选一个数字放入该位置,此时方案数位ans*=sum
}
befor = now; //更新befor的值
}
printf("%lld\n",max(ans,0));
}
return 0;
}

So easy

Description lsz学长最近迷上了一个叫做lkwg的游戏,他发现一个宠物受到不同的技能伤害后会增加不同的捕捉几率,现在lsz学长

特别想要获得这个宠物,但是他十分纠结他能否获得它。lsz学长可以确定如果你把这个宠物的捕捉几率提升到k及k以上

的时候,lsz学长就可以捕捉到它。lsz学长现在心急如焚,所以想请聪明的你帮忙解决问题(强制性的)!

Input

宠物最初捕捉几率为0,第一行输入两个数n、k,代表有n个技能,k如题意。第二行是n个用空格分隔的数,分别代表每一个技能能使用多少次

第三行也是n个用空格分隔的数,代表每一个技能可以增加多少捕捉几率

第四行还是n个用空格分隔的数,代表每一个技能的代价

Output 如果可以捕捉输出最小的代价

否则输出NO

Sample Input 1
4 5
1 1 1 1
1 2 3 4
4 3 2 1
Sample Output 1
3

题解如下:

#include<iostream>
using namespace std; int A[15],B[15],C[15];
int n,k; int min_spent = 1e9;
void dfs(int level,int chance,int spent)
{ //level第几个技能,chance捕捉概率,捕捉花费
if(spent >= min_spent || level > n)
return;
if(chance >= k)
{
min_spent = spent;
return;
}
for(int i = 0;i <= A[level];i ++)
{
dfs(level+1,chance + i*B[level],spent + i*C[level]);
}
} int main()
{
cin>>n>>k;
int sum = 0;
for(int i = 0;i < n;i++)
cin>>A[i];
for(int i = 0;i < n;i++)
{
cin>>B[i];
sum += A[i]*B[i];
}
for(int i = 0;i < n;i++)
cin>>C[i];
if(sum < k)
{
cout<<"NO";
}
else
{
dfs(0,0,0);
cout<<min_spent;
}
return 0;
}

奇偶交换

Description

LSZ学长喜欢将奇数和偶数交换,于是就想考大家一个问题。给你一个很大的数n,(0<=n<=10^100),如果这个数的位数中相邻位置的数是一奇一偶的情况下,就可以交换这两个位置上的数,你可以进行无数次的操作,LSZ想让你求出操作后可以达到的最小的值,如果有前导0的情况把前导零输出

Input t组输入(0<t<100),每组输入一个数n,(0<=n<=10^100)

Output 输出操作后的最小的数

Sample Input 1

3
0709
1337
246432
Sample Output 1
0079
1337
234642

Hint 第一个输入的样例中,输入的第一个数0709你可以交换相邻位置的的0(偶数)和7(奇数)然后变成0079此时这个数最小

思路如下: 对于字符串中的每一个数字如果是偶数(奇数)的话无路他怎么变换,它相对其它偶数(奇数)的位置是不会改变的,所以我们可以把奇偶数单独分离开(顺序不变),在奇偶数之间进行比较,把小的放前边,这题的一个比较也是一个难点,这时候的比较我们可以用两个指针来实现比较操作

题解如下

#include<iostream>
#include<string> using namespace std;
int main()
{
int t;
cin>>t;
while(t--)
{
string str;
cin>>str;
int even[1000];
int odd[1000];
int pos_even = 0;
int pos_odd = 0;
for(int i=0;i<str.size();i++)
if((str[i]-'0')%2 == 0)
even[pos_even++] = str[i] - '0';
else
odd[pos_odd++] = str[i] - '0';
if(pos_even == 0)
{
for(int i=0;i<pos_odd;i++)
cout<<odd[i];
}
else if(pos_odd == 0)
{
for(int i=0;i<pos_even;i++)
cout<<even[i];
}
else
{
int *p_odd = &odd[0],*p_even = &even[0];
while(p_odd != &odd[pos_odd] && p_even != & even[pos_even])
{
if(*p_odd < *p_even)
{
cout<<*p_odd;
p_odd++;
}
else
{
cout<<*p_even;
p_even++;
} }
if(p_odd != &odd[pos_odd])
{
while(p_odd != &odd[pos_odd])
{
cout<<*p_odd;
p_odd++; }
}
else
{
while(p_even != &even[pos_even])
{
cout<<*p_even;
p_even++;
}
}
}
cout<<endl;
}
return 0;
}

聚餐

Description

众所周知ACM工作室有一个传统,就是每年大三大四的学长学姐会请大一大二的吃饭,在聚餐的时候每个人都有一个独特的编号,编号为1~n(1<n<32768),LSZ的编号为n,如果和LSZ是同一届的,那么他的编号和LSZ的编号有大于1的公约数,否则都是不和他一届的,LSZ想知道有多少人和他不是同一届的,请你通过编程计算出来

Input t组输入(1<=t<=1000),每组输入一个数n(1<n<32768)

Output 输出一个数,表示和LSZ不是同一届的人数

Sample Input 1

2
25608
24027
Sample Output 1
7680
16016

思路如下:

这题类似于素数筛选的算法,比如n%2==0,表示2和n不互素,那么2的倍数和n都有2这个公因数,也不会互素,然后把2的倍数全都标记,这个算法类似于素数筛选

题解如下:

#include<iostream>
#include<string.h> using namespace std;
int vis[40000];
int n; void Solve()
{
memset(vis,0,sizeof(vis));
for(int i = 2;i <= n;i ++)
{
if(! vis[i])
{
if(n % i == 0)
{
for(int j = i;j <= n;j += i)
{
vis[j] = 1;
}
}
}
} } int main()
{
int t;
scanf("%d",&t);
while(t--)
{
cin>>n;
int sum = 0;
Solve();
for(int i = 1;i <= n;i ++)
{
if(! vis[i])
{
sum++;
}
} printf("%d\n",sum);
}
return 0;
}

LSZ的签到题(大数相加问题)

Description 既然是签到题,那么就没必要出的太难了。给你两个正整数a,b,请你输出a+b的值

Input t组输入,每组输入两个数a,b(0<=a,b<=10^100)

Output 输出a+b的值

Sample Input 1

2
10000 100
0123 03
Sample Output 1
10100
126

题解如下:

#include<iostream>
#include<cstring> using namespace std;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
char a[100000],b[100000]; //定义存储字符串
scanf("%s %s",a,b);
int A[100000] = {0},B[100000] = {0}; //转存倒叙转存到,A、B数组中
int LEN_a = (int)strlen(a);
int LEN_b = (int)strlen(b);
for(int i = LEN_a - 1;i >= 0;i --)
{
A[LEN_a - i - 1] = a[i] - '0';
}
for(int i = LEN_b - 1;i >= 0;i --)
{
B[LEN_b - i - 1] = b[i] - '0';
}
int max_LEN;
if(LEN_a > LEN_b)
max_LEN = LEN_a;
else
max_LEN = LEN_b;
for(int j = 0;j < max_LEN;j ++)
{
A[j] += B[j];
}
for(int k = 0;k < max_LEN+10;k ++) //对A数组的每一位进行进位处理
{
if(A[k] > 9)
{
A[k+1] += A[k] / 10;
A[k] %= 10;
}
}
int digit = max_LEN + 10;
while(digit > 0 && A[digit] == 0) //去掉数组最后边的0
{
digit--;
}
for(int l = digit;l >= 0;l --)
printf("%d",A[l]);
printf("\n"); } return 0;
}

Description(数据范围不大 dfs爆搜)

YZJ学长有一个问题想请教大家

给出两个整数m,n(0<=n<=m<10^20),YZJ学长想知道m除第一位外的每一位经过‘+’或‘-’运算后的结果等于n的方案数量

例如 m=1111,n=0,方案:1+1-1-1=0,1-1-1+1=0,1-1+1-1=0 方案数量:3

例如 m=21,n=1,方案:2-1=1 方案数量:1

Input

多组数据输入

第一行输入m和n用空格隔开

Output

输出所有的方案个数

Sample Input 1

1111 0

Sample Output 1

3

Sample Input 2

21 1

Sample Output 2

1

Sample Input 3

11111111111111111111 2
Sample Output 1
3
Sample Output 2
3
Sample Output 3
92378

题解如下:

#include<iostream>
#include<string.h>
using namespace std;
long long int n;
int br[1000000];
long long int ans;
long long int LEN_ar; int pos = 0;
void dfs(int k,int zhi)
{
if(k == LEN_ar-1)
{
if(zhi == n-br[0])
ans++;
return;
}
dfs(k + 1,zhi + br[k+1]);
//dfs(k + 1,zhi + br[pos+1]); 注意这里的 br[pos+1] 一定不要这样写,因为,pos并不是 dfs的一个参数,所以在每一次dfs自己调用自己的时候pos的值都是0,我就是愣了半天硬是没看出来 每一次(pos+1)值均是不变的
dfs(k + 1,zhi - br[k+1]);
//dfs(k + 1,zhi - br[pos+1]); } int main()
{
char ar[100000];
while(cin>>ar>>n)
{
pos = 0;
ans = 0;
LEN_ar = (int)strlen(ar);
for(int i = 0;i < LEN_ar;i ++)
br[i] = ar[i] - '0';
dfs(0,0);
cout<<ans<<endl;
}
return 0;
}

2019NYIST计科第七次周赛总结的更多相关文章

  1. 2019NYIST计科第四次周赛

    YZJ的牛肉干 Description 今年的ACM暑期集训队一共有18人,分为6支队伍.其中有一个叫做 YZJ的大佬,在共同的集训生活中,大家建立了深厚的友谊, YZJ准备做点什么来纪念这段激情燃烧 ...

  2. 基于SCRUM方法实践的西油计科党建设计与实现

    基于SCRUM方法实践的西油计科党建设计与实现 序言 所属课程 https://edu.cnblogs.com/campus/xnsy/2019autumnsystemanalysisanddesig ...

  3. 北工大耿丹学院16级计科院3班C语言课程助教学期总结

    很荣幸得到邹老师,周老师,以及北工大耿丹学院各位老师的认可,担任计科院3班C语言课程助教,班主任为李光杰老师,很感谢李老师一学期的帮助,使得我更好的担任助教一职.我班学生31名,很愉快的与同学们度过一 ...

  4. 用HTML+CSS编写一个计科院网站首页的静态网页

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. 计科1111-1114班第一次实验作业(NPC问题——回溯算法、聚类分析)

    实验课安排 地点: 科技楼423 时间:  计科3-4班---15周周一上午.周二下午 计科1-2班---15周周一下午.周二晚上(晚上时间从18:30-21:10) 请各班学委在实验课前飞信通知大家 ...

  6. 基于SCRUM方法实践的西油计科党建设计与实现-个人实践流程清单

    基于SCRUM方法实践的西油计科党建设计与实现 个人实践流程清单 一.Alpha版本冲刺个人在SCRUM团队任务清单: 时间 我这个三天做了什么 实际解决燃尽图项目数量 我遇到了什么问题 我下一个三天 ...

  7. Java课程设计-算术运算测试(D级) 齐鲁工业大学 计科20-1 王瀚垠 202003010033

    Java课程设计-算术运算测试(D级) 齐鲁工业大学 计科20-1 王瀚垠 202003010033 目录 1.项目简介 2.项目采用技术 3.功能需求分析 4.项目亮点 5.项目功能架构图和UML类 ...

  8. 1415-2 计科&计高 软件工程博客&Github地址汇总-修正版

    序号 标识 博客 代码 1 1121袁颖 joanyy joanyy 2 1122崔琪 chitty ChittyCui 3 1123吕志浩 lucy123 715lvzhihao 4 1124张静 ...

  9. 2017<java技术>预备作业计科冀浩然

    1.阅读邹欣老师的博客,谈谈你期望的师生关系是什么样的? 我期望的师生关系是相互融洽的,老师能够在上课的时候尽量多的教我们专业知识,可以尽量多和我们进行互动,课下能和我们如同朋友一般就可以了. 2.你 ...

随机推荐

  1. mongoose .find().limit()返回undefined

    当我们使用mongoose的find方法查询数据库的同时,可以使用limit方法来指定返回数据的条数. limit方法基本语法如下所示: >db.COLLECTION_NAME.find().l ...

  2. 负margin在页面布局中的应用

    关于负margin的原理建议大家看看这篇文章:http://www.cnblogs.com/2050/archive/2012/08/13/2636467.html#2457812 一. 左右列固定, ...

  3. vue的子组件不能进行router的切换

    在用vue开发过程中,偶然一次使用在子组件中进行router的切换,发现不起作用,后来才反应过来,子组件只是一个组件,vue的路由的切换只能是在父组件(也就是真正的页面)里面进行跳转!

  4. Flink系列之状态及检查点

    Flink不同于其他实时计算的框架之处是它可以提供针对不同的状态进行编程和计算.本篇文章的主要思路如下,大家可以选择性阅读. 1. Flink的状态分类及不同点. 2. Flink针对不同的状态进行编 ...

  5. 看逐浪CMS技术小哥做SVG动画(附使用Bodymovin和Lottie将Adobe After Effects(AE)程式转为 HTML5/Android/iOS原生的动画全过程-即AE转svg\canvas\html5动画)

      名词解解释 adobe After Effects AE:adobe After Effects,adobe公司的专业视频制作软件. Bodymovin插件预览 Bodymovin:是一个AE的插 ...

  6. PageRank 算法初步了解

    前言 因为想做一下文本自动摘要,文本自动摘要是NLP的重要应用,搜了一下,有一种TextRank的算法,可以做文本自动摘要.其算法思想来源于Google的PageRank,所以先把PageRank给了 ...

  7. Win10下如何安装和搭建appium自动化测试环境

    转:https://www.cnblogs.com/huainanhai/p/11577419.html 安装Android SDK https://www.jianshu.com/p/2acdc1d ...

  8. python基础(初识)

      Python简介 python的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏姆(中文名字:龟叔)为了在阿姆斯特丹打发时间,决心开发一个新的脚本解 ...

  9. 关于beforeRouteEnter中的next()

    beforeRouteEnter(to,from, next){ console.log(this)   //undefined next(vm => { console.log(vm)}) } ...

  10. 机器学习 - LSTM应用之情感分析

    1. 概述 在情感分析的应用领域,例如判断某一句话是positive或者是negative的案例中,咱们可以通过传统的standard neuro network来作为解决方案,但是传统的神经网络在应 ...