ABC 481 糖丸之赛+题解
省流:题解只有 ABCD。
A
输出 \(A+B\) 的答案的位数,一个 \(if\) 判断是否大于 \(9\) 即可。
但我没想那么多,下意识打了个:
ll a=read(),b=read();
ll x=a+b,ans=0;
while(x){
ans++;
x/=10;
}
write(ans);
感觉有点乃,不过无所谓了。
B
给出 \(n\) 个点 \((1,a_1),(2,a_2)...(n,a_n)\),连成一条折线,问与直线 \(y=k\) 的交点。
枚举每一个点(\(1\) ~ \(n-1\)),如果下一个点和这一个点的纵坐标分别大于和小于 \(k\),答案++。
如果这个点横坐标不为 \(1\) 且纵坐标为 \(k\),那么答案一定会多算一次(自己推一下),减 \(1\) 即可。
代码奉上
#include<bits/stdc++.h>
#define ll long long
#define rep(a,b,c) for(ll (a)=(b);(a)<=(c);(a)=-~(a))
#define wep(a,b,c) for(ll (a)=(b);(a)>=(c);(a)=~-(a))
#define tep(a,b) for(auto (a):b)
using namespace std;
const ll mod=1e9+7;
const ll N=1e3+10;
ll jie[N],jie_ni[N];
namespace io{
inline ll read() {
ll t=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-') f=-f;
ch=getchar();
}
while(ch>='0'&&ch<='9') {
t=t*10+ch-'0';
ch=getchar();
}
return t*f;
}
inline void write(ll x) {
if(x<0) {putchar('-');x=-x;}
if(x>=10) {write(x/10);}
putchar(char(x%10+'0'));
}
}
namespace maths{
ll quick(ll a,ll b){
ll sum=1;
while(b){
if(b&1){
sum*=a;
sum%=mod;
}
a*=a;
a%=mod;
b>>=1;
}
return sum;
}
void init(){
jie[0]=1;
jie_ni[0]=1;
rep(i,1,N-2){
jie[i]=jie[i-1]*i%mod;
}
jie_ni[N-2]=quick(jie[N-2],mod-2);
wep(i,N-3,1){
jie_ni[i]=jie_ni[i+1]*(i+1)%mod;
}
}
ll C(ll n,ll m){
if(n<m||n<0||m<0){
return 0;
}
return (jie[n]*jie_ni[m]%mod*jie_ni[n-m]%mod)%mod;
}
}
using namespace io;
using namespace maths;
ll a[N];
int main(){
ll n=read(),k=read(),ans=0;
bool last=0;
rep(i,1,n){
a[i]=read();
}
rep(i,1,n-1)
if((a[i]>=k&&a[i+1]<=k)||(a[i]<=k&&a[i+1]>=k)){
ans++;
if(a[i]==k&&i!=1)
ans--;
}
write(ans);
return 0;
}
C
令 \(cnt\) 为 \(0\)。
有 \(q\) 个人依次前来,如果他是第一次来,编号为 ++\(cnt\),输出这每次来的人的编号。
用 \(map\) 储存每个字符串的编号,如果不为 \(0\) 就直接输出,否则输出 ++\(cnt\) 并将此值赋给这个字符串。
代码奉上。
#include<bits/stdc++.h>
#define ll long long
#define rep(a,b,c) for(ll (a)=(b);(a)<=(c);(a)=-~(a))
#define wep(a,b,c) for(ll (a)=(b);(a)>=(c);(a)=~-(a))
#define tep(a,b) for(auto (a):b)
using namespace std;
const ll mod=1e9+7;
const ll N=4e5+10;
ll jie[N],jie_ni[N];
namespace io{
inline ll read() {
ll t=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-') f=-f;
ch=getchar();
}
while(ch>='0'&&ch<='9') {
t=t*10+ch-'0';
ch=getchar();
}
return t*f;
}
inline void write(ll x) {
if(x<0) {putchar('-');x=-x;}
if(x>=10) {write(x/10);}
putchar(char(x%10+'0'));
}
}
namespace maths{
ll quick(ll a,ll b){
ll sum=1;
while(b){
if(b&1){
sum*=a;
sum%=mod;
}
a*=a;
a%=mod;
b>>=1;
}
return sum;
}
void init(){
jie[0]=1;
jie_ni[0]=1;
rep(i,1,N-2){
jie[i]=jie[i-1]*i%mod;
}
jie_ni[N-2]=quick(jie[N-2],mod-2);
wep(i,N-3,1){
jie_ni[i]=jie_ni[i+1]*(i+1)%mod;
}
}
ll C(ll n,ll m){
if(n<m||n<0||m<0){
return 0;
}
return (jie[n]*jie_ni[m]%mod*jie_ni[n-m]%mod)%mod;
}
}
using namespace io;
using namespace maths;
map<string,ll> f;
int main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
ll q;
cin>>q;
ll cnt=0;
rep(i,1,q){
string s;
cin>>s;
if(!f[s]){
f[s]=++cnt;
}
write(f[s]);
putchar('\n');
}
return 0;
}
D
有 \(n\) 个点,\(m\) 条有向边,对于每一个向外连边的点,它和它可到达的点中编号最小的点边权为 \(0\),其余为 \(1\)。
初始给每个边赋值为 \(1\),然后遍历每一个点,把它和它可到达的点中编号最小的点边权改为 \(0\),跑一边 \(dij\) 即可。
然后我唐了,\(dij\) 大于号打成小于号查了半天。
代码奉上。
#include<bits/stdc++.h>
#define ll long long
#define rep(a,b,c) for(ll (a)=(b);(a)<=(c);(a)=-~(a))
#define wep(a,b,c) for(ll (a)=(b);(a)>=(c);(a)=~-(a))
#define tep(a,b) for(auto &(a):b)
using namespace std;
const ll mod=1e9+7;
const ll N=1e6+10;
ll jie[N],jie_ni[N];
namespace io{
inline ll read() {
ll t=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-') f=-f;
ch=getchar();
}
while(ch>='0'&&ch<='9') {
t=t*10+ch-'0';
ch=getchar();
}
return t*f;
}
inline void write(ll x) {
if(x<0) {putchar('-');x=-x;}
if(x>=10) {write(x/10);}
putchar(char(x%10+'0'));
}
}
namespace maths{
ll quick(ll a,ll b){
ll sum=1;
while(b){
if(b&1){
sum*=a;
sum%=mod;
}
a*=a;
a%=mod;
b>>=1;
}
return sum;
}
void init(){
jie[0]=1;
jie_ni[0]=1;
rep(i,1,N-2){
jie[i]=jie[i-1]*i%mod;
}
jie_ni[N-2]=quick(jie[N-2],mod-2);
wep(i,N-3,1){
jie_ni[i]=jie_ni[i+1]*(i+1)%mod;
}
}
ll C(ll n,ll m){
if(n<m||n<0||m<0){
return 0;
}
return (jie[n]*jie_ni[m]%mod*jie_ni[n-m]%mod)%mod;
}
}
using namespace io;
using namespace maths;
vector<pair<ll,ll>> g[N];
ll dist[N];
int main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
ll n=read(),m=read(),s=read(),t=read();
rep(i,1,m){
ll x=read(),y=read();
g[x].push_back({y,1});
}
rep(i,1,n){
ll mn=1e18;
tep(gh,g[i]){
mn=min(mn,gh.first);
}
tep(gh,g[i]){
if(gh.first==mn){
gh.second=0;
}
}
}
priority_queue<pair<ll,ll>,vector<pair<ll,ll>>,greater<pair<ll,ll>>> q;
rep(i,0,N-2){
dist[i]=1e18;
}
q.push({0,s});
dist[s]=0;
while(!q.empty()){
ll tx=q.top().second,val=q.top().first;
// cout<<"tx="<<tx<<",val="<<val<<endl;
q.pop();
if(dist[tx]<val)
continue;
tep(gh,g[tx]){
ll ty=gh.first,v=gh.second;
// cout<<"ty="<<ty<<",v="<<v<<endl;
if(dist[ty]>dist[tx]+v){
dist[ty]=dist[tx]+v;
q.push({dist[ty],ty});
}
}
}
if(dist[t]>=1e17){
write(-1);
}
else{
write(dist[t]);
}
return 0;
}
E
开 E 的时候才 \(20\)+\(eps\) 分钟,感觉这次比赛很水,说不定来得及切 F。
有 \(n\) 个点,如何画一条直线,分成两大块,是的较多的那一块中点最多
然后很快有了思路,把所有点按“顺时针”排序,随后双指针即可。
但排序貌似涉及到了我未曾涉及的神秘数学知识,搏斗 \(40min\) 最终放弃
F
发现可以在 \(BFS\) 时用上一层的点集体更新答案,但没时间了调不出来,空悲切。
G
没看题(bushi。
然后没了。
我再也不写神秘数学题了 \(555\)。

浙公网安备 33010602011771号