开始: 2022-08-13 00:00:00

2022summer8

结束: 2022-08-13 00:00:00
当前: 2025-0505-3131 12:47:46  类型:IOI 状态:已经结束 

B

#include<bits/stdc++.h>
using namespace std;
int tim[100010],pri[100010],head=1,tail=0;
//用队列存储当前有用的优惠票 需要建两个队列 一个存储时间 一个存储价格
//从head到tail都是队列中的元素
int main()
{
freopen("transfer.in","r",stdin);
freopen("transfer.out","w",stdout);
int n,ans=0;
scanf("%d",&n);
for(int i=1; i<=n; i++)
{
int opt,p,t;
scanf("%d%d%d",&opt,&p,&t);
if(opt==0)
{
tail++;//tail++把优惠券存在tail的位置
tim[tail]=t;
pri[tail]=p;
//如果坐的是地铁,直接将票价和时间加入队列
ans+=p;//坐地铁一定会花钱
}
else
{
int flag=0;
//0表示还没有找到符合条件的优惠票
//非0表示最早的符合条件的优惠票编号为flag
while(t-tim[head]>45&&head<=tail) head++;
//需要保证队列中有元素 即head<=tail
//队头是最早入队的优惠票 如果超时了 出队
for(int j=head; j<=tail; j++)
{
if(pri[j]>=p)//如果这个优惠票价格大于p 可以用
{
flag=j;//最早的符合条件的优惠票编号为flag
pri[j]=0;//把价格置零表示这张优惠票已经用过了
break;//退出循环
}
}
if(flag==0) ans+=p;//如果用了优惠票则不用出钱,否则还是要付钱的
}
}
printf("%d",ans);
return 0;
}

C

#include<bits/stdc++.h>
using namespace std;
int p1,p2,p3,len;
char s[110];
bool check(int i)//展开的条件是减号两遍的字符均为数字或均为小写字母 并且右边大于左边
{
if(s[i-1]>='0'&&s[i-1]<='9'&&s[i+1]>='0'&&s[i+1]<='9'&&s[i-1]<s[i+1]) return 1;
if(s[i-1]>='a'&&s[i-1]<='z'&&s[i+1]>='a'&&s[i+1]<='z'&&s[i-1]<s[i+1]) return 1;
return 0;
}
int main()
{
freopen("expand.in","r",stdin);
freopen("expand.out","w",stdout);
scanf("%d%d%d",&p1,&p2,&p3);
scanf("%s",s);
len=strlen(s);
for(int i=0;i<len;i++)
{
if(s[i]=='-'&&check(i))//如果需要展开
{
if(p1==3)
{
for(int j=s[i-1]+1;j<=s[i+1]-1;j++)
for(int k=1;k<=p2;k++) printf("*");
//注意填充*也要因为p2翻倍
}
else
{
int f=0;//如果是数字或p1=1
if(s[i-1]>='a'&&s[i-1]<='z'&&p1==2) f='a'-'A'; //如果是字母且需要转化为大写字母 就-32('a'-'A'=32)
if(p3==1)//顺序
{
for(int j=s[i-1]+1;j<=s[i+1]-1;j++) //j是字符的ascii码
for(int k=1;k<=p2;k++) printf("%c",j-f);
}
else//逆序
{
for(int j=s[i+1]-1;j>=s[i-1]+1;j--)
for(int k=1;k<=p2;k++) printf("%c",j-f);
}
}
}
else printf("%c",s[i]);//不需要展开就正常输出
}
return 0;
}

D

#include<bits/stdc++.h>
using namespace std;
int cnt;
int c[10];
int book[10];
int rule[10][10];
char a[40];
int ans[1234567],k;
void mul(int x)//高精度乘法 ans(高精度)*=x(低精度)
{
for(int i=1;i<=ans[0];i++) ans[i]*=x;//乘法
ans[0]++;//最高位可能有进位 所以位数++
for(int i=1;i<=ans[0];i++) //进位
{
ans[i+1]+=ans[i]/10;
ans[i]=ans[i]%10;
}
while(ans[ans[0]]==0&&ans[0]>1) ans[0]--;//去除前导0
}
void dfs(int x)//当前遍历到了x这个数字
{
book[x]=1;//做标记 防止重复遍历
cnt++; //每遍历到一个新数字 cnt++
for(int i=0;i<=9;i++)
{
if(rule[x][i]&&book[i]==0) dfs(i);
}
}
int main()
{
freopen("create.in","r",stdin);
freopen("create.out","w",stdout);
cin>>a>>k;
for(int i=1;i<=k;i++)
{
int u,v;
scanf("%d%d",&u,&v);
rule[u][v]=1;//有一条u->v的规则
}
for(int i=0;i<=9;i++) rule[i][i]=1;//显然可以从自己变到自己 相当于没有变
for(int i=0;i<=9;i++)
{
for(int j=0;j<=9;j++) book[j]=0;//把标记数组清零
cnt=0;
dfs(i);//从i开始搜索它能够变化成的数字
c[i]=cnt;//i这个数字有cnt种变化方式
}
ans[0]=1; ans[1]=1;//做乘法要初始化ans=1
//ans[0]存储答案的长度 后面从低位到高位存储具体的数
int len=strlen(a);
for(int i=0;i<len;i++) mul(c[a[i]-'0']); //把每个数字变化方式的数量相乘 要用高精度
for(int i=ans[0];i>=1;i--) cout<<ans[i];//从高位到低位输出答案
return 0;
}