A Station and Bus
传送门
陈述题
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define rush() int T;scanf("%d",&T);while(T--)
#define mm(a,b) memset(a,b,sizeof(a))
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define sc(a) scanf("%d",&a)
#define sc2(a,b) scanf("%d%d",&a,&b)
#define pf(a) printf("%d\n",a)
#define pf2(a,b) printf("%d %d\n",a,b)
#define p_f(a) printf("%d ",a)
#define fi first
#define se second
#define db double
#define ll long long
using namespace std;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
const db eps=1e-9;
string s;
int main()
{
cin>>s;
if(s!="AAA"&&s!="BBB")cout<<"Yes"<<endl;
else cout<<"No"<<endl;
return 0;
}
B Count Balls
传送门
陈述题
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define rush() int T;scanf("%d",&T);while(T--)
#define mm(a,b) memset(a,b,sizeof(a))
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define sc(a) scanf("%d",&a)
#define sc2(a,b) scanf("%d%d",&a,&b)
#define pf(a) printf("%d\n",a)
#define pf2(a,b) printf("%d %d\n",a,b)
#define p_f(a) printf("%d ",a)
#define fi first
#define se second
#define db double
#define ll long long
using namespace std;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
const db eps=1e-9;
ll n,a,b;
int main()
{
cin>>n>>a>>b;
if(a+b==0)cout<<0<<endl;
ll ans=n/(a+b)*a+min(n%(a+b),a);
cout<<ans<<endl;
return 0;
}
C Tax Increase
传送门
先算出max(ceil(a/0.08),ceil(b/0.1)),再看这个数能回去否?
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define rush() int T;scanf("%d",&T);while(T--)
#define mm(a,b) memset(a,b,sizeof(a))
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define sc(a) scanf("%d",&a)
#define sc2(a,b) scanf("%d%d",&a,&b)
#define pf(a) printf("%d\n",a)
#define pf2(a,b) printf("%d %d\n",a,b)
#define p_f(a) printf("%d ",a)
#define fi first
#define se second
#define db double
#define ll long long
using namespace std;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
const db eps=1e-9;
int a,b;
int main()
{
cin>>a>>b;
int t1=ceil(a*1.0/0.08),t2=ceil(b*1.0/0.1);
int t=max(t1,t2);
int a1=floor(t*0.08),a2=floor(t*0.1);
if(a1==a&&a2==b)pf(t);
else pf(-1);
return 0;
}
D String Formation
传送门
用
d
e
q
u
e
deque
deque再加个反转标记实现
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define rush() int T;scanf("%d",&T);while(T--)
#define mm(a,b) memset(a,b,sizeof(a))
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define sc(a) scanf("%d",&a)
#define sc2(a,b) scanf("%d%d",&a,&b)
#define pf(a) printf("%d\n",a)
#define pf2(a,b) printf("%d %d\n",a,b)
#define p_f(a) printf("%d ",a)
#define fi first
#define se second
#define db double
#define ll long long
using namespace std;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
const db eps=1e-9;
deque<char>q;
string s;
int qq,com,f;
char c;
int main()
{
cin>>s>>qq;
rep(i,0,s.size()-1)q.push_back(s[i]);
bool flag=true;
rep(i,1,qq){
cin>>com;
if(com==1)flag=!flag;
else{
cin>>f>>c;
if(flag){
if(f==1)q.push_front(c);
else q.push_back(c);
}else{
if(f==2)q.push_front(c);
else q.push_back(c);
}
}
}
if(flag){
while(!q.empty()){
cout<<q.front();
q.pop_front();
}
}else{
while(!q.empty()){
cout<<q.back();
q.pop_back();
}
}
return 0;
}
E Divisible Substring
传送门
必须明白取余证明
那么天大的数我们也能知道这个数是不是能整除
p
p
p
如果枚举的话
O
(
n
2
)
O(n^2)
O(n2)肯定不行的
那么考虑从后往前算余数,并且记录余数出现的个数,比如算到第
i
i
i位,此时余数为
1
1
1,但是先前有余数为
1
1
1的个数为
2
2
2,那么也就是说我们可以直接从第
i
i
i位到那两个贡献前面的位置作为一个子字符串,因为此时前面正好能整除
p
p
p,从数学方面考虑下,
(
1
0
n
∗
a
+
b
)
%
m
o
d
=
1
(10^n*a+b)\%mod=1
(10n∗a+b)%mod=1,因为
b
%
m
o
d
=
1
b\%mod=1
b%mod=1,又因为
10
10
10与
p
p
p互质,那么必然
a
%
m
o
d
=
0
a\%mod=0
a%mod=0,非常巧妙的方法,但是素数还要格外考虑一下
2
2
2和
5
5
5,因为
10
10
10与之不互质,这两个数都有个特点就是最后一位都和这两个取模为
0
0
0,也就是从前往后考虑,直接累加当前第几位,也就是几种选择。
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define rush() int T;scanf("%d",&T);while(T--)
#define mm(a,b) memset(a,b,sizeof(a))
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define sc(a) scanf("%d",&a)
#define sc2(a,b) scanf("%d%d",&a,&b)
#define pf(a) printf("%d\n",a)
#define pf2(a,b) printf("%d %d\n",a,b)
#define p_f(a) printf("%d ",a)
#define fi first
#define se second
#define db double
#define ll long long
using namespace std;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
const db eps=1e-9;
const int N=1e4+5;
int n,p,cnt[N];
string s;
int main()
{
cin>>n>>p>>s;
int size=s.size();
ll ans=0;
if(p==2||p==5)rep(i,0,size-1){if((s[i]-'0')%p==0)ans+=i+1;}
else{
ll base=1,now=0;
cnt[0]=1;
per(i,size-1,0){
now=(((s[i]-'0')*base)%p+now)%p;
base=(base*10)%p;
ans+=cnt[now];++cnt[now];
}
}
cout<<ans<<endl;
return 0;
}
F Removing Robots
传送门
这个题我的做法可能有点繁琐,首先肯定要按起始坐标轴排序,然后考虑
d
p
[
i
]
dp[i]
dp[i]表示最后集合中第
i
i
i个机器人为最后一个的集合个数,其中
d
p
[
0
]
dp[0]
dp[0]表示为空集,那么如果每个机器人没有
D
D
D这个范围,那么就从左往右考虑,
d
p
[
i
]
=
d
p
[
i
]
+
d
p
[
0
∼
j
]
dp[i]=dp[i]+dp[0\sim j]
dp[i]=dp[i]+dp[0∼j],也就是到了第
i
i
i位,把这个机器人放到前面那些集合的尾部即可,但是每个机器人此时有
D
D
D的范围,那么什么情况下会让部分集合不存在呢?考虑前面有的机器人激活后的范围已经触及到
x
i
x_i
xi了,那么这个机器人前面的那些集合必然不行,再加强一下,也就是说找到每个机器人左边第一个范围触及到他的起始坐标的,然后把找到的这个机器人前边的
d
p
dp
dp前缀和减去就是答案。可以看出最后需要维护出每个机器人左边第一个能触及到他的机器人,这块可以用个优先队列处理下(详见代码),之后当算出一个
d
p
[
i
]
dp[i]
dp[i]后,对于
i
i
i后面所有
d
p
dp
dp都要加上这个值,那么用差分数组帮助实现,再维护一个
d
p
dp
dp的前缀和数组
s
u
m
sum
sum用来减去对应的值即可。
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define rush() int T;scanf("%d",&T);while(T--)
#define mm(a,b) memset(a,b,sizeof(a))
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define sc(a) scanf("%d",&a)
#define sc2(a,b) scanf("%d%d",&a,&b)
#define pf(a) printf("%d\n",a)
#define pf2(a,b) printf("%d %d\n",a,b)
#define p_f(a) printf("%d ",a)
#define fi first
#define se second
#define db double
#define ll long long
using namespace std;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
const db eps=1e-9;
const int N=2e5+5;
const int P=998244353;
pii robs[N];
int n,cop[N],ner[N];
ll dp[N],sum[N],bb[N];
struct eff{
int l,r,id;
bool operator < (const eff a)const{
return id<a.id;
}
};
priority_queue<eff>q;
int findd(int x){return upper_bound(cop+1,cop+n+2,x)-cop;}
int main()
{
sc(n);
rep(i,1,n)sc2(robs[i].fi,robs[i].se);
sort(robs+1,robs+n+1);
rep(i,1,n)cop[i]=robs[i].fi;
cop[n+1]=inf;
rep(i,1,n){
while(!q.empty()){
auto u=q.top();
if(i>u.r)q.pop();
else if(i>=u.l&&i<=u.r&&!ner[i]){
ner[i]=u.id;
break;
}else break;
}
int nx=robs[i].fi+robs[i].se-1,pos=findd(nx);
q.push({i+1,pos-1,i});
}
bb[1]++;sum[0]=1;dp[0]=1;
rep(i,1,n){
bb[i]=(bb[i]+bb[i-1])%P;
dp[i]=(dp[i]+bb[i])%P;
if(ner[i]>0)dp[i]=((dp[i]-sum[ner[i]-1])%P+P)%P;
bb[i+1]=(bb[i+1]+dp[i])%P;
sum[i]=(dp[i]+sum[i-1])%P;
//cout<<dp[i]<<" "<<sum[i]<<endl;
}
cout<<sum[n]<<endl;
return 0;
}
本文深入解析了五道ACM竞赛题目,包括A题StationandBus的字符串匹配,B题CountBalls的数学求解,C题TaxIncrease的数学算法,D题StringFormation的数据结构应用,以及E题DivisibleSubstring的取余证明和高效算法。每道题目均附有详细的代码实现和思路讲解。

514

被折叠的 条评论
为什么被折叠?



