普及组模拟赛
1.Problem 1. 小 X 的加法难题
Input file: sum.in
Output file: sum.out
Time limit: 1 second
Memory limit: 256 MB
第一节编程课上,老师要求大家写一个程序计算两个正整数的和。
看到小 X 不屑的眼神后,老师决定给小 X 增加难度。以求 12 和 3 的和为例,老师在 12 + 3 这个
原始式子里加入一些无用的空格,再把它交给小 X。
这下小 X 傻眼了,希望你帮帮他。
Input
第一行包含一个字符串,表示老师给小 X 的式子。
Output
若式子的结果不超过 108,则第一行包含一个整数,表示式子的结果;否则第一行包含一个字符串
“Large”。
Example
sum.in sum.out
1 2 + 3
15
23456789+98765432
Large
Scoring
• 对于 30% 的数据,式子中不包含无用的空格,式子的结果不超过 108。 • 对于 100% 的数据,字符串长度不超过 100。
题意分析
这题就是给出一个算式,然后求和,判断是否超过108
解题思路
这题可以用long long 来做
一个一个累加,如果超过108就退出
我这里用的是高精度
特判一下108 就行了
AC代码
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int o,o1,a[205],b[205],c[205];
string s;
void add()//高精加
{
int t=0;
for(int i=200;i>=1;i--)
{
c[i]=(t+a[i]+b[i])%10;
t=(a[i]+b[i]+t)/10;
}
}
int main()
{
freopen("sum.in","r",stdin);
freopen("sum.out","w",stdout);
getline(cin,s);
int len=s.size(),ok=0;
for(int i=len-1;i>=0;i--)//取数
if(s[i]!=' ')
{
if(s[i]!='+'&&ok==0){
o++;a[201-o]=s[i]-48;}
if(s[i]=='+')ok=1;
if(s[i]!='+'&&ok==1){
o1++;b[201-o1]=s[i]-48;}
}
add();//相加
int j=1;
while(c[j]==0)j++;//处理0
ok=0;
if(200-j+1==9)//特判
{
if(c[j]!=1)ok=1;
for(int i=j+1;i<=200;i++)if(c[i]!=0){
ok=1;break;}
}
if(200-j+1>9)ok=1;
if(ok==1)printf("Large");//输出
else for(int i=j;i<=200;i++)printf("%d",c[i]);
return 0;
}
2.Problem 2. 小 X 的密码破译
Input file: password.in
Output file: password.out
Time limit: 1 second
Memory limit: 256 MB
这天小 Y 有事外出,小 X 又忘记带电脑了,于是想使用小 Y 的电脑。不幸的是,小 Y 设了密码,
密码提示是四个整数,且输错后密码和提示就会重新生成。
正当小 X 一筹莫展的时候,他打开小 Y 的抽屉,发现里面有一张小纸条,上面写着:“给出提示
n, a, b, c,令 di = (ai2 + bi + c) mod 11111111(1 ≤ i ≤ n),将序列 d 去除重复的数后从小到大排序得到
序列 e,设序列 e 有 m 个数,则密码为 (∑mi=1 iei) mod 11111111。”
小 X 十分激动,想立刻完成密码破译,希望你帮帮他。
Input
第一行包含四个整数 n, a, b, c。
Output
第一行包含一个整数,表示密码。
Example
password.in password.out
3 0 0 2
2
5 1 2 3
380
Scoring
• 对于 30% 的数据,n ≤ 103。 • 对于 60% 的数据,n ≤ 105。 • 对于 100% 的数据,1 ≤ n ≤ 107,0 ≤ a, b, c ≤ 100。
题意分析
这题就是给你一些数,然后按照它的提示模拟
注意:∑mi=1 iei 是 指for(int i=1;i<=m;i++)e[i]乘i;
解题思路
一遍一遍模拟
AC代码
#include<cstdio>
using namespace std;
const long long MOD=11111111;
long long n,a,b,c,s,n1,d[10000005],f[MOD+5];
int main()
{
freopen("password.in","r",stdin);
freopen("password.out","w",stdout);
scanf("%lld%lld%lld%lld",&n,&a,&b,&c);
for(int i=1;i<=n;i++)//暴力模拟
{
long long o=(i%MOD)*(i%MOD)%MOD;
f[((a%MOD)*(o%MOD)%MOD+(b%MOD)*(i%MOD)%MOD+c)%MOD]=1;
}
for(int i=0;i<=MOD;i++)if(f[i]==1)d[++n1]=i;//模拟
for(int i=1;i<=n1;i++)//模拟
s=((d[i]%MOD)*(i%MOD)%MOD+s)%MOD;
printf("%lld",s%MOD);
return 0;
}
3.Problem 3. 小 X 的液体混合
Input file: mixture.in
Output file: mixture.out
Time limit: 1 second
Memory limit: 256 MB
虽然小 X 不喜欢化学原理,但他特别喜欢把一大堆液体倒在一起。
现在小 X 有 n 种液体,其中 m 对会发生反应。现在他想把这 n 种液体按某种顺序倒入一个容器
内,让他获得最刺激的体验,也就是使危险系数尽量大。
我们可以这样计算危险系数,一开始容器内没有任何液体,危险系数为 1。每次液体倒入容器时,
若容器内已有一种或多种液体会与这种液体发生反应,则危险系数会乘 2,否则危险系数不变。
最大危险系数小 X 不会算,希望你帮帮他。
Input
第一行包含两个整数 n, m。
接下来 m 行,每行包含两个整数 a, b,表示液体 a 和液体 b 会发生反应。
Output
第一行包含一个整数,表示最大危险系数。
Example
mixture.in mixture.out
3 2
1 2
2 3
4
Scoring
• 对于 30% 的数据,n ≤ 10。 • 对于 100% 的数据,1 ≤ n ≤ 1000,a = b,同种反应不会出现多次。
题意分析
这题就是将液体倒在一起
求2发生反应次数
解题思路
这题我们可以用连通分块来做
求一共有多少个集合
答案为2n-集合个数
注意要用高精乘(位数弄多一点>400)
AC代码
#include<cstdio>
using namespace std;
int a,b,o,n,m,c[2005],fa[1005];
int find(int x)//找祖先
{
if(fa[x]==x)return x;
return fa[x]=find(fa[x]);
}
void gjc()//高精乘
{
int t=0;
for(int i=2000;i>=1;i--)
{
int x=c[i]*2+t;
t=x/10;
c[i]=x%10;
}
}
int main()
{
freopen("mixture.in","r",stdin);
freopen("mixture.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)fa[i]=i;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&a,&b);
fa[find(a)]=find(b);//并查集求连通块
}
for(int i=1;i<=n;i++)
if(fa[i]==i)o++;//连通块个数
c[2000]=1;
for(int i=1;i<=n-o;i++)//乘2
gjc();
int j=1;
while(c[j]==0)j++;//高精度
for(int i=j;i<=2000;i++)
printf("%d",c[i]);
return 0;
}
4.Problem 4. 小 X 的 AK 计划
Input file: plan.in
Output file: plan.out
Time limit: 1 second
Memory limit: 256 MB
在小 X 的家乡,有机房一条街,街上有很多机房。每个机房里都有一万个人在切题。小 X 刚刷完
CodeChef,准备出来逛逛。
机房一条街有 n 个机房,第 i 个机房的坐标为 xi,小 X 的家坐标为 0。小 X 在街上移动的速度为
1,即从 x1 到 x2 所耗费的时间为 |x1 x2|。
每个机房的学生数量不同,ACM 题目水平也良莠不齐。小 X 到达第 i 个机房后,可以花 ti 的时间
想题,然后瞬间 AK;当然,也可以过机房而不入。
小 X 现在只有 m 个单位时间,之后他就该赶着去打 Codeforces 了。现在他想知道自己最多能在多
少个机房 AK,希望你帮帮他。
Input
第一行包含两个整数 n, m。
接下来 n 行,每行包含两个整数 xi, ti。
Output
第一行包含一个整数,表示小 X 最多能 AK 的机房数量。
Example
plan.in plan.out
2 10
1 100
5 5
1
Scoring
• 对于 30% 的数据,n ≤ 20。 • 对于 60% 的数据,n ≤ 1000。 • 对于 100% 的数据,1 ≤ n ≤ 105,0 ≤ m, xi ≤ 1018,0 ≤ ti ≤ 109。
题意分析
有一条街道上面有n个机房
距离为 |x[i]-x[j]|
每个机房要用t[i]的时间AK
现在有m个时间
求最多AK几个机房
20分解题思路
dfs暴力
20代码
#include<algorithm>
#include<iostream>
#include<cstdio>
using namespace std;
long long n,m,mmax,x[100005],t[100005],d[100005];
void dfs(long long xx,long long s,long long min)
{
if(min<0)return;//时间为0就退出
mmax=max(s,mmax);//找最多AK机房数
if(mmax==n)return;
for(long long i=1;i<=n;i++)//枚举每一个机房
if(d[i]==0)
{
d[i]=1;
long long y=abs(x[i]-xx)+t[i];
if(y<=min)dfs(x[i],s+1,min-y);
d[i]=0;
}
return;
}
int main()
{
freopen("plan.in","r",stdin);
freopen("plan.out","w",stdout);
scanf("%lld%lld",&n,&m);
for(long long i=1;i<=n;i++)
scanf("%lld%lld",&x[i],&t[i]);
dfs(0,0,m);
printf("%lld",mmax);
return 0;
}
总结
这次比赛第二题没有发挥好
预估:100+100+30+30=260
实际:100+30+30+20=180
要多学会优化+剪枝