博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[20180813]校内模拟赛
阅读量:5961 次
发布时间:2019-06-19

本文共 5459 字,大约阅读时间需要 18 分钟。

T1 加 (add)

题目描述

你有一个变量x,一开始为0。

你还有n种操作,第i种操作可以进行至多ki次,每次可以让x变为min(x+ai,hi)。

求x最大能变到多少。

输入格式

第一行一个正整数n。

接下来n行,每行三个正整数,表示ai,hi,ki。

输出格式

输出一个整数,表示答案。

样例

样例输入

78 35 15 35 115 35 18 35 110 35 14 35 12 35 1

样例输出

35

数据范围

​ 对于 40%的数据,? ≤ 10,?? = 1,ℎ? ≤ 100且所有ℎ?相等。

​ 对于 100%的数据,? ≤ 100,?? ≤ 30,ℎ? ≤ 104,?? ≤ 200。

附加说明

​ 如果你觉得太简单,可以把这题的数据范围当成:

​ ? ≤ 106,??,ℎ?,?? ≤ 1018。

Solution

显然h小的先做更优,排序后模拟即可

把每种操作看成x=min(x+a*k,h),注意判\(a\ *\ k\)爆long long的情况,由于文件较大需要用fread优化

#include
#include
#include
#define ll long longusing namespace std;char B[1<<26],*S=B;inline ll read(){ ll x;char c; while((c=*S++)<'0'||c>'9'); for(x=c-'0';(c=*S++)>='0'&&c<='9';)x=x*10+c-'0'; return x;}#define MN 1000005long long n,a[MN],h[MN],k[MN],id[MN];bool cmp(const long long&x,const long long&y){return h[x]
2e18) now=h[id[i]]; else now=min(now+a[id[i]]*k[id[i]],h[id[i]]); printf("%lld\n",now); return 0;}

T2 减(minus)

问题描述

S 君是秘密组织“TB”的成员,现在他要执行一项潜入任务。潜入地点可以抽象为一张?个点?条边的无向

图,点编号为1到?,每条边上设有警戒设备,第?条边上的警戒值为??,警戒值越高代表经过这条边时越危

险。现在 S 君已经位于1号节点,他需要到位于?号节点的数据库上窃取数据。

为了 S 君的安全,S 君的搭档小 N 会在后方提供支援,小 N可以让至多?条边上的警戒设备在这次潜入任

务中暂时失效。小N 的目标是让 S 君执行任务时需要经过的最危险的有效警戒设备的警戒值尽可能小,请你

求出这个值。

输入格式

第一行三个整数?,?,?。 接下来?行,每行三个整数??,??,??,表示有一条连接??,??且

警戒值为??的边。

输出格式

输出一个整数,表示答案,如果不能完成任务,输出−1,如果可以不经过任何有效警戒设备,输出0。

样例

样例输入

5 7 1 1 2 5 3 1 4 2 4 8 3 2 3 5 2 9 3 4 7 4 5 6

样例输出

4

数据范围

对于全部数据, ? ≤ 1000, 0 ≤ ? ≤ ? ≤ 104, 1 ≤ ?? ≤ 106。数据可能有一定梯度。

附加说明

如果你觉得太简单,可以把这题的数据范围当成:

?,? ≤ 106,? ≤ ?,1 ≤ ?? ≤ 109。

Solution

二分答案后用最短路求1到n最少经过多少条大于答案的边,不超过k即合法。要求的最短路边权只有0和1,

可以直接bfs,走长度为0的边拓展出的点直接放在队头优先拓展,答案只要二分是第几大的边权,时间复杂

度O((n+m)logm)

#include
#include
#include
#include
char B[1<<26],*S=B;inline int read(){ int x;char c; while((c=*S++)<'0'||c>'9'); for(x=c-'0';(c=*S++)>='0'&&c<='9';)x=x*10+c-'0'; return x;}#define MM 1000005#define MN 1000005#define mid (l+r>>1) int n,m,k;struct edge{int to,w,nex;}e[MM<<1];int cnt,hr[MN];int id[MM],W[MM<<1],MAXW;inline void ins(int x,int y,int w){ e[++cnt]=(edge){y,1,hr[x]};hr[x]=cnt;W[cnt]=w; e[++cnt]=(edge){x,1,hr[y]};hr[y]=cnt;W[cnt]=w; id[cnt>>1]=cnt;}int d[MN],q[MM<<1],hq,tq;bool mark[MN];inline void bfs(){ memset(d,127,sizeof d); memset(mark,false,sizeof mark);register int i; for(d[q[hq=tq=MN]=1]=0;hq<=tq;hq++)if(!mark[q[hq]]){ mark[q[hq]]=true;int D=d[q[hq]];if(D>k) break; for(i=hr[q[hq]];i;i=e[i].nex)if(!mark[e[i].to]&&d[e[i].to]>D+e[i].w){ if(e[i].w==1) d[q[++tq]=e[i].to]=D+1; else d[q[hq--]=e[i].to]=D; } } }bool check(int x){ register int i; for(i=1;i<=cnt;i++) e[i].w=W[i]>x?1:0; bfs();return d[n]<=k; }inline bool cmp(const int&x,const int&y){ return W[x]
m) return 0*puts("-1"); if(r<1) return 0*puts("0"); printf("%d\n",W[id[ans]]); return 0;}

T3 乘(product)

问题描述

求有多少个?位数各位数字的乘积为?。

这里的?位数字可以有前导0,但前导0同样算入乘积中。

输入格式

一行两个整数?,?。

输出格式

输出一个整数,表示答案。

样例

样例输入

2 0

样例输出

19

数据范围

对于 20%的数据,? ≤ 6。

对于 50%的数据,? ≤ 16。

另有 30%的数据,? = 0。

对于 100%的数据,1 ≤ ? ≤ 50,0 ≤ ? ≤ 109。

附加说明

如果你觉得太简单,可以把这题的数据范围当成:1 ≤ ? ≤ 50,0 ≤ ? ≤ 1018。

Solution

  1. k=0直接枚举第一个0的出现位置,在此之前必须是1~9,在此之后可以是0~9,高精度算一下就好了

  2. k>0时预处理k的所有因数,\(f_{i,j}\)表示前i位乘积为第j种因数的方案数,转移可以预处理一下每种因数乘上

    1~9会变成哪种因数,考虑2,3,5,7四种质因子,10^18内只由这四种质因子组成的最多因数的数也只有

    7680个,所以可以轻松AC

#include
#include
#include
#include
#include
using namespace std;#define Base 100000000#define Width 8long long n,k;struct HPint{ long long s[10],len; void init(){memset(s,0,sizeof s);len=0;} void PLUS(HPint o){ for(;s[len]==0&&len>0;len--); len=max(len,o.len); for(int i=1;i<=len;i++){if((s[i]+=o.s[i])>=Base) s[i+1]++,s[i]-=Base;} len++;for(;s[len]==0&&len>0;len--); } void MUL(int o){ for(;s[len]==0&&len>0;len--); for(int i=1;i<=len;i++) s[i]*=o; for(int i=1;i<=len;i++){ s[i+1]+=s[i]/Base; s[i]%=Base; }len+=2; for(;s[len]==0&&len>0;len--); } void print(){ for(;s[len]==0&&len>0;len--); if(len==0) printf("0"); else{printf("%lld",s[len]);for(int i=len-1;i>=1;i--)printf("%08lld",s[i]);} }}f[55][15500];long long num2,num3,num5,num7,N,num1,sum;long long n2,n3,n5,n7;inline int getnum(long long &div,int a){ int ret=0; while(div%a==0) ret++,div/=a; return ret;}map
mp;long long fac[15500],pin;int next[15500][15];int main(){ freopen("product.in","r",stdin); freopen("product.out","w",stdout); cin>>n>>k; register long long i,j,l,m;HPint ans,res;ans.init(); if(k==0){ for(i=1;i<=n;++i){ res.init();res.len=res.s[1]=1; for(j=1;j
i;--j)res.MUL(10); ans.PLUS(res); } ans.print();return 0; } N=k; num2=getnum(N,2); num3=getnum(N,3); num5=getnum(N,5); num7=getnum(N,7); if(N!=1) return 0*puts("0"); n2=n3=n5=n7=1; for(int i=0;i<=num2;i++){ n3=n5=n7=1; for(int j=0;j<=num3;j++){ n5=n7=1; for(int l=0;l<=num5;l++){ n7=1; for(int m=0;m<=num7;m++){ long long NUM=n2*n3*n5*n7; fac[++pin]=NUM; mp[NUM]=pin; fac[++pin]=k/NUM; mp[k/NUM]=pin; n7*=7; } n5*=5; } n3*=3; } n2<<=1; } for(i=1;i<=pin;i++)for(j=1;j<10;j++) next[i][j-1]=mp[fac[i]*j]; f[0][1].len=f[0][1].s[1]=1; for(i=0;i
<=pin;++j) for(l=1;l<=9;++l)if(next[j][l-1]) f[i+1][next[j][l-1]].PLUS(f[i][j]); f[n][mp[k]].print(); return 0;}

Blog来自PaperCloud,未经允许,请勿转载,TKS!

转载于:https://www.cnblogs.com/PaperCloud/p/9470642.html

你可能感兴趣的文章
Linux Namespace系列(09):利用Namespace创建一个简单可用的容器
查看>>
博客搬家了
查看>>
Python中使用ElementTree解析xml
查看>>
jquery 操作iframe、frameset
查看>>
解决vim中不能使用小键盘
查看>>
jenkins权限管理,实现不同用户组显示对应视图views中不同的jobs
查看>>
我的友情链接
查看>>
CentOS定时同步系统时间
查看>>
批量删除用户--Shell脚本
查看>>
Eclipse Java @Override 报错
查看>>
知道双字节码, 如何获取汉字 - 回复 "pinezhou" 的问题
查看>>
linux中cacti和nagios整合
查看>>
Python高效编程技巧
查看>>
Kafka服务端脚本详解(1)一topics
查看>>
js中var self=this的解释
查看>>
Facebook 接入之获取各个配置参数
查看>>
linux的日志服务器关于屏蔽一些关键字的方法
查看>>
事情的两面性
查看>>
只要会营销,shi都能卖出去?
查看>>
sed单行处理命令奇偶行输出
查看>>