A:智乃的Hello XXXX
题目描述
智乃最近学习了C语言,在她学会编写 hello world 程序以后举一反三,还设计了一个hello XXXX的程序。
该程序可以通过“人工”智能自动识别,并向别人打招呼。
比如智乃在运行这段程序时就可以输出"hello chino",清楚运行的时候就会自动输出"hello qingchu"。
现在,开发这个“人工”智能程序的任务就交给你啦。
输入描述:
(本题无输入)
输出描述:
请向自己打招呼吧,输出一行一个字符串"hello XXXX",其中XXXX可以为任意字符串,包括空字符串。
示例1
输入
(None)
输出
hello chino
示例2
输入
(None )
输出
hello world
不能再水的一道题,只是让你输出hello…即可
各种答案都可以,主要是体现special judge
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
//#define int long long
#define debug(a) cout<<#a<<" = "<<a<<endl;
typedef double db;
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef long long ll;
const int inf = 0x3f3f3f3f;
//signed main()
int main()
{
ios_base::sync_with_stdio(false), cin.tie(0);
printf("hello Jacob\n");
return 0;
}
B:智乃买瓜
题目描述
有一人前来买瓜。
“哥们儿,这瓜多少钱一斤呐”
“两块钱一斤”
“What’s up,这瓜皮是金子做的,还是瓜粒子是金子做的”
智乃来到水果摊前买瓜,水果摊上贩卖着N个不同的西瓜,第i个西瓜的重量为wi。智乃对于每个瓜都可以选择买一个整瓜或者把瓜劈开买半个瓜,半个瓜的重量为wi/2 。
也就是说对于每个西瓜,智乃都有三种不同的决策:
1.购买一整个重量为wi的西瓜
2.把瓜劈开,购买半个重量为wi/2的西瓜
3.不进行购买操作
为了简化题目,我们保证所有瓜的重量都是一个正偶数。
现在智乃想要知道,如果他想要购买西瓜的重量和分别为k=1,2,3…M时,有多少种购买西瓜的方案,因为这些数字可能会很大,请输出方案数对 10^9+7 取余数后的结果。
输入描述:
第一行输入两个整数N,M(0≤N≤10 ^ 3 ,1≤M≤10^3),分别表示西瓜的数目N,以及查询的重量上限为M。
若N不为0,接下来一行N个正偶数wi(2<=wi<=2*10^3)表示每个西瓜的重量。
输出描述:
输出一行M个数字,分别表示购买西瓜的重量和为k=1,2,3…M时,有多少种购买西瓜的方案,因为这些数字可能会很大,请输出方案数对 10^9+7 取余数后的结果。
示例1
输入
3 6
8 2 4
输出
1 2 1 3 2 3
说明
购买重量和为1的西瓜共1种方案:
①、2号西瓜劈开买半个。
购买重量和为2的西瓜共2种方案:
①、直接购买2号西瓜。
②、3号西瓜劈开买半个。
购买重量和为3的西瓜共1种方案:
①、2号西瓜劈开买半个再加上3号西瓜劈开买半个。
购买重量和为4的西瓜共3种方案:
①、1号西瓜劈开买半个。
②、直接购买2号西瓜,再加上3号西瓜劈开买半个。
③、直接购买3号西瓜。
购买重量和为5的西瓜共2种方案:
①、2号西瓜劈开买半个再加上直接购买3号西瓜。
②、2号西瓜劈开买半个再加上1号西瓜劈开买半个。
购买重量和为6的西瓜共3种方案:
①、直接购买2号西瓜,再加上直接购买3号西瓜。
②、1号西瓜劈开买半个,再加上直接购买2号西瓜。
③、1号西瓜劈开买半个,再加上3号西瓜劈开买半个。
示例2
输入
16 30
2 2 2 6 8 10 12 6 6 6 16 8 30 28 28 2
输出
4 10 20 37 65 109 174 269 401 580 817 1128 1525 2024 2640 3396 4304 5386 6660 8153 9880 11870 14138 16713 19605 22850 26462 30471 34881 39725
示例3
输入
3 5
100 102 104
输出
0 0 0 0 0
对于这个题我们可以想得简单一点,我们可以将这N个不同种类的西瓜,每个西瓜拆分成等质量的两份新的西瓜,这时每两份新的西瓜是属于同一种西瓜,因此我们很容易就想到,现在每种西瓜最多能选两个,这样一来,我们就可以套多重背包的模板求取方案的数量了。
用朴素多重背包就行,无需用二进制优化,算了一下时间复杂度为O(N * M),实际上是 O(2 * N * M),“2”表示西瓜数,可以忽略不计,算出来大概在2e6,在合法的范围内。
注意,多重背包中的体积对应题中输入的查询重量上限m,价值对应的是西瓜的重量。
以下是对西瓜进行转化之后的分析:
状态表示:
集合:dp[i][j] 所有只从前 i 种西瓜中选,且总重量恰好为 j 的方案的集合
属性:数量 count
状态计算:
和 多重 背包一致,根据最后一步选0, 1,2块瓜分类
不包含西瓜 i 的所有选法:
dp[i][j] = dp[i-1][j]
包含k个西瓜 i 的所有选法(k = 1 or 2)
dp[i][j] = dp[i-1][j-k*ai]
状态转移方程:
总的方案数 = 不包含西瓜 i 的所有选法 + 包含k个西瓜 i 的所有选法
dp[i][j] = dp[i-1][j]+dp[i-1][j-k*ai]
状态初始化 and 答案:
初始化:
dp[0][0]=1,初始 M 为 0 时,一个不选也是一种方案,其它均为 0(dp[0][1,2,3,…])
答案:dp[n][1,2,…,m]即为根据题目意思要求的答案
代码
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
//#define int long long
#define debug(a) cout<<#a<<" = "<<a<<endl;
typedef double db;
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef long long ll;
const int inf = 0x3f3f3f3f;
//
int n,m;//西瓜的数目,以及查询的重量上限为
const int N = 1e3+10,M = 1e3+10,mod = 1e9+7;
int w[N];
int s[N];
int dp[N][N];
//signed main()
int main()
{
ios_base::sync_with_stdio(false), cin.tie(0);
cin>>n>>m;
int W;
for(int i=1;i<=n;++i)
{
cin>>W;
s[i]=2 , w[i] = W/2;
}
dp[0][0] = 1;//这种情况
for(int i=1;i<=n;++i)
{
for(int j=0;j<=m;++j)
{
for(int k=0;k*w[i]<=j&&k<=s[i];++k)
{
dp[i][j]=(dp[i][j]+dp[i-1][j-k*w[i]])%mod;
}
}
}
for(int i=1;i<m;++i) cout<<dp[n][i]<<' ';
cout<<dp[n][m]<<endl;
return 0;
}
D:智乃的01串打乱
题目描述
智乃有一个长度为N仅有字符’0’′和’1’ 组成的字符串,现在智乃想把这个01串打乱,变得和之前不一样。请你将这个01串打乱后输出。
打乱指的是,打乱后的01串和原本的01串中字符’0’和’1’ 的数目相同,字符串长度相同,且至少存在一个位置上的字符不同。
输入描述:
第一行输入一个正整数N(2≤N≤10^5)表示01串的长度。
接下来一行输入一个仅由字符’0’和’1’ 组成的字符串,保证其中字符0和1都至少出现一次。
输出描述:
仅一行,一个打乱后的01串,要求和原串至少有一个位置上的字符不同。
示例1
输入
2
01
输出
10
示例2
输入
10
1110101010
输出
0101010111
在字符串中,随便找到一对不相同的字符,将两者swap一下就行。
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
//#define int long long
#define debug(a) cout<<#a<<" = "<<a<<endl;
typedef double db;
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef long long ll;
const int inf = 0x3f3f3f3f;
//
const int N = 1e5+10;
int n;
string s;
//signed main()
int main()
{
ios_base::sync_with_stdio(false), cin.tie(0);
cin>>n;
cin>>s;
for(int i=1;i<s.size();++i)
if(s[i]!=s[i-1])
{
swap(s[i],s[i-1]);break;
}
cout<<s<<endl;
return 0;
}
L:智乃的数据库
题目描述
智乃最近在学习数据库的查询语言SQL。SQL (Structured Query Language:结构化查询语言) 是用于管理关系数据库管理系统(RDBMS)。 SQL 的范围包括数据插入、查询、更新和删除,数据库模式创建和修改,以及数据访问控制。
使用SQL,可以灵活的对数据库表进行操作,在数据库的查询语句中有"GROUP BY"这样一种关键字。
GROUP BY 语句用于结合聚合函数,根据一个或多个列对结果集进行分组。
例如数据库中储存了这样一个数据库表Table,执行带有"GROUP BY"关键字的查询语句。
SELECT COUNT(*) FROM Table GROUP BY name;
SQL语句中COUNT表示聚合后每一个组中有多少条数据。
当执行上述的SQL查询语句后,其返回的结果如下
2
2 1
第一行的2表示按照name字段进行分组聚合,一共可以分出2组。
第二行的两个整数表示每组中各有多少条数据。
当然了,"GROUP BY"关键字是可以选中多个列进行分组聚合的,只需要把这些字段用逗号隔开即可。
SELECT COUNT(*) FROM Table GROUP BY name,val;
例如这样的SQL查询语句,执行后返回的结果如下
3
1 1 1
现在智乃把这张数据库表导出给你,请你执行一个SELECT COUNT(*) FROM Table GROUP BY …;的查询语句,请你把查询的结果告诉智乃。
为了简化问题,我们假设数据库的表由NN条记录以及MM个字段组成,且这些字段的类型均为int类型。
输入描述:
输出描述:
示例1
输入
4 3
id name val
1 1 2
1 1 3
1 2 1
2 2 2
SELECT COUNT(*) FROM Table GROUP BY name,id;
输出
3
1 2 1
说明
你可以按照自己喜欢的顺序输出
例如
3
2 1 1
则也能得到正确的结果。
主要是哈希表unordered_map,会用就行
注意:cin/scanf和getline的混用要注意的地方
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
int n,m;
const int N = 1010;
string s[N];
string ss;
unordered_map<string,int> usi[N];
int main()
{
scanf("%d%d",&n,&m);
for(int i=0;i<m;++i) cin>>s[i];
for(int i=0;i<n;++i)
{
for(int j=0;j<m;++j)
{
scanf("%d",&usi[i][s[j]]);
}
}
getchar();//一定要注意把上方scanf产生的回车给吃掉下面才能getline
getline(cin,ss);
string sss = ss.substr(36);//下标为35的时候出现第一个逗号,因此我们要取其后面的子串才能分离出我们要分组的关键词
vector<string> vs(N);
int pos = 0;
unordered_map<string,bool> usb;
//这里一定要注意代码的书写以免debug
for(int i=0;i<sss.size();++i)
{
if(sss[i]==','||sss[i]==';') { usb[vs[pos]] = true, pos++; continue;}
if(sss[i]!=','&&i!=sss.size()-1)
vs[pos]+=sss[i];//分离出关键词
}
unordered_map<string,int> usi2;
set<string> ss;
for(int i=0;i<n;++i)
{
string ssss;
for(auto x : usi[i])
{
string c = to_string(x.second);
if(usb[x.first]) ssss+=c,ssss+=",";//每加入一个数值产生的字符串注意要用","隔开,如果不加“,”会被hack
}
usi2[ssss]++;//每一组的数目加一
ss.insert(ssss);//将当前组加入set
}
printf("%d\n",ss.size());//由于set有自动去重的功能,因此直接输出其大小就知道有多少个不同的组别
for(auto x : usi2) printf("%d ",x.second);//输出每一组有多少个元素
printf("\n");
return 0;
}