目录
A. Many Equal Substrings
字符串的叠加问题只要是前面的和后面的一样的话前面的就不用再出现了只需要找到最大的出现的前面和后面即可,所以我们选择直接暴力即可(数据范围较小)
void solve(){
cin>>n>>m;
string s; cin>>s;
int pos = 0;
for(int i=0;i<n;i++)
if(s.substr(0,i)==s.substr(n-i,i)) pos=i;
string add = s.substr(pos);
cout<<s;
m--;
while(m--) cout<<add;
cout<<endl;
return ;
}
B. Creating the Contest
明显的具有双指针的性质所以我们直接使用双指针即可
void solve(){
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
int ans = 0;
for(int i=1;i<=n;i++){
int j = i;
while(j+1<=n and a[j+1]<=2*a[j]) j++;
ans = max(ans,j-i+1);
i=j;
}
cout << ans << endl;
return ;
}
C. Maximal Intersection
左右区间的覆盖我们考虑使用multiset来维护,然后找左右匹配就可以知道其实就是区间的交集
void solve(){
cin>>n;
multiset<int> L,R;
for(int i=1;i<=n;i++){
int l,r; cin>>l>>r;
L.insert(l);
R.insert(r);
seg[i]={l,r};
}
int ans = 0;
for(int i=1;i<=n;i++){
auto [l,r]=seg[i];
L.erase(L.find(l));
R.erase(R.find(r));
int maxl= *L.rbegin();
int minr= *R.begin();
ans = max(ans,minr-maxl);
L.insert(l);
R.insert(r);
}
cout << ans << endl;
return ;
}
D. Concatenated Multiples
区间的拼接,我们可以发现最后是由两个部分组成一个是前面的一个是后面的,前面的贡献来源于本身以及后面数的数位,所以我们考虑预处理每一个数后面添加数的位数之后的贡献,然后对于后面的数只需要去找这个数在后面的时候的答案贡献即可(注意自己和自己拼接)
map<int,int> mp[15];
int t,n,m;
int a[N];
int ten[20];
void solve()
{
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];
ten[0]=1;
for(int i=1;i<=15;i++) ten[i]=10*ten[i-1];
for(int i=1;i<=10;i++)
for(int j=1;j<=n;j++){
int x=a[j]%m*(ten[i]%m)%m;// 我多了这么多%的数需要+mod m 为x的数
// 表示我在这个数后面需要 衔接 的数的余数
mp[i][(m-x)%m]++;
}
int ans=0;
for(int i=1;i<=n;i++){
int cnt=0;
int x=a[i];
while(x) x/=10,cnt++;
ans+=mp[cnt][a[i]%m];
string s=to_string(a[i]);
s=s+s;
int ok=0;
for(int i=0;s[i];i++){
ok=(ok*10+(s[i]-'0'))%m;
}
if(!ok) ans--;
}
cout<<ans<<endl;
return ;
}
E. Tree with Small Distances
我们有个明显的贪心策略就是从权重最大的人的父节点开始操作,如果他的父节点被标记了的话就直接把他父节点的儿子节点也标记,同时注意如果可以在dfs外操作的尽量在dfs外操作否则就一定要理清楚是不是可以递归的,此题我们采用外面取操作即可
ector<int> g[N];
int f[N],d[N];
bitset<N> st;
void dfs(int u,int fa){
if(~fa){
d[u]=d[fa]+1;
f[u]=fa;
}
for(auto&v:g[u]){
if(v==fa) continue;
dfs(v,u);
}
}
void solve(){
cin>>n;
for(int i=1;i<n;i++){
int a,b; cin>>a>>b;
g[a].push_back(b);
g[b].push_back(a);
}
dfs(1,-1);
priority_queue<PII> q;
for(int i=1;i<=n;i++) if(d[i]>2) q.push({d[i],i});
int ans = 0;
while(!q.empty()){
auto [d,v]=q.top(); q.pop();
if(st[v]) continue;
ans ++ ;
st[v]= true;
int u = f[v];
st[u]=true;
for(auto&v:g[u]) st[v]=true;
}
cout << ans << endl;
return ;
}
F. Multicolored Markers
我们直接按照题目意思去模拟即可,不要自己想到啥就是啥,我们可以知道如果说构造的矩形中能包括a构成的一个小矩形或者包括b的小矩形的话就是ok的所以直接检查即可
void solve()
{
int a,b; cin>>a>>b;
int sum=a+b;
vector<PII> A,B;
for(int i=1;i<=a/i;i++){
if(a%i==0){
A.push_back({i,a/i});
}
}
for(int i=1;i<=b/i;i++){
if(b%i==0){
B.push_back({i,b/i});
}
}
auto check = [&](int x,int y){
for(auto&[a,b]:A){
if(x>=a && y>=b) return true;
}
for(auto&[a,b]:B){
if(x>=a && y>=b) return true;
}
return false;
};
int ans=3e18;
for(int i=1;i<=sum/i;i++){
if(sum%i==0){
if(check(i,sum/i)){
ans=min(ans,2*(i+sum/i));
}
}
}
cout<<ans<<endl;
return ;
}