A. Legs
-------------------------------------题解------------------------------
经典鸡兔同笼,数据范围不大,跑暴力就行
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
if(n<=2) cout<<1<<'\n';
else
{
cout<<n/4+(n%4!=0)<<'\n';
}
}
}
B. Scale
-----------------------------------------题解----------------------------
题目规定一定是合法的所以只需要稍微调整一下二重for循环让i++变成i+=m就行
点击查看代码
#include<bits/stdc++.h>
using namespace std;
char a[1005][1005];
char b[1005][1005];
int main()
{
int t;
cin>>t;
while(t--)
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
cin>>a[i][j];
}
}
int x=1,y=1;
for(int i=1;i<=n;i+=m)
{
for(int j=1;j<=n;j+=m)
{
b[x][y]=a[i][j];
y++;
}
if(x==n/m) break;
y=1;
x++;
}
for(int i=1;i<=x;i++)
{
for(int j=1;j<=y-1;j++)
{
cout<<b[i][j];
}
cout<<endl;
}
}
}
C. Sort
------------------------------题解-------------------------
其实翻译一下就是要让a串和b串拥有的字母一样,给你一个l,r区间查询区间内有几个字母不一样,之前想过前缀和的办法没跑对,后来还是决定暴力,处理了一整个字符串中每个位置上下的字母差别的前缀和数量,只需要查询的时候相减就好了
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int c[27][N];
int main()
{ ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin>>t;
while(t--)
{
int n,q;
cin>>n>>q;
string a="",b="";
cin>>a>>b;
a=" "+a;
b=" "+b;
map<char,int> m1,m2;
for(int i=0;i<=n;i++)
{
for(int j=1;j<=26;j++)c[i][j]=0;
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=26;j++)
{
c[i][j]=c[i-1][j];
if(j==int (a[i]-'a'+1)) c[i][j]++;
if(j==int(b[i]-'a'+1)) c[i][j]--;
}
}
while(q--)
{
int l,r;
cin>>l>>r;
int cnt=0;
for(int i=1;i<=26;i++)
{
cnt+=abs(c[r][i]-c[l-1][i]);
}
cout<<cnt/2<<'\n';
}
}
}
/*
1
7 4
abbccde
ppbccab
*/
D. Fun
------------------------------题解------------------------------
看到这种题,首先想到推公式,推公式不行想优化暴力,这题我一直想推公式,结果最后是需要优化暴力
我们假定a<=b<=c由题目给出的第二个公式可以知道aa + aa + aa <= ab + bc + ca<= n由此可以优化一重a 只跑a从1到aa3<=n的循环,b也一样我们只需要跑b*b<=n的循环就够了
我们再想办法去优化b由于由公式2变化可知(x-(a*b))/(a+b)>=c ,c<=x-a-b,我们要把c的值在两个当中去min值,累加起来就是答案
点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int t,n,x;
ll cnt;
void solve(){
for(int a=1;a*a*3<=n;a++){
for(int b=a;b*b<=n;b++){
if(a+b>=x) break;
if(a*b+a+b>n) break;
int fk=(n-a*b)/(a+b);
int ck=min(fk,x-a-b);
if(ck<b) continue;
//计算贡献
if(a==b){
cnt++;//a=b=c
cnt+=(ck-b)*3;
}
else{
cnt+=3;
cnt+=(ck-b)*6;
}
}
}
}
int main(){
cin>>t;
while(t--){
cin>>n>>x;
cnt=0;
solve();
cout<<cnt<<endl;
}
}
E. Decode
好题!
----------------------------题解--------------------------------
能看到这里的都是糕手了,我主要讲解思路。题意找[l,r]的对数,没对至少有一组x,y满足条件。
我们用一个变量now记录前缀中0和1的差值 现在我们这样假设有这样一个数组11011 now的变化不就会是1 2 1 2 3 整个数组里是不是有两个1与两个2,会看字符串,当x=2 y=3,
x=3,y=4的时候符合题目要求 我们以其中一个x=2,y=3为例,它可以满足(n-y)*x对[l,r]使其符合条件。这是一段的,我们要计算多段的,我在代码中采用的是> > 固定右边界 然后把左边界累加起来> 这里很难,要着重理解一下比如11010有两段now都是1,map记录了每一段now为1的时候他前面有几个数字可选
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod=1e9+7;
signed main()
{
int t;
cin>>t;
while(t--)
{
string s;
cin>>s;
int n=s.size();
map<int,int>m;
int now=0;
m[0]=1;
ll ans=0;
for(int i=0;i<n;i++)
{
if(s[i]=='1') now++;
else now--;
ans+=((n-i)*m[now])%mod;
m[now]=(m[now]+i+2)%mod;
}
cout<<ans<<'\n';
}
}
F.Bomb
-------------------------题解-----------------------------------
二分出一个值,使得数组中每个数减小到超过这个数的值,然后利用等差数列,知道a[i]-b[i](公差),首项a[i],末项(首相-公差)的次数来求得每个a[i]给最后的答案贡献了多少,最后输出
点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
ll a[N];
ll b[N];
ll n,k;
ll x1=0;
bool check(ll x)
{ ll cnt=0;
for(ll i=1;i<=n;i++)
{
if(a[i]<x) continue;
else cnt+=(a[i]-x)/b[i]+1;
}
if(cnt>=k) return 0;
return 1;
}
ll su1(ll sx, ll d, ll n1) {
ll mx=sx-d*(n1-1);
return (sx + mx) * n1 / 2;
}
int main()
{
int t;
cin>>t;
while(t--)
{
cin>>n>>k;
x1=0;
for(ll i=1;i<=n;i++) cin>>a[i];
for(ll i=1;i<=n;i++) cin>>b[i];
ll l=0,r=1e9;
while(l<=r)
{
ll mid=(l+r)/2;
if(check(mid)==1) r=mid-1;
else x1=mid,l=mid+1;
}
x1++;
ll ans=0;
for(ll i=1;i<=n;i++)
{ if(a[i]<x1) continue;
ll time=(a[i]-x1)/b[i]+1;
ans+=su1(a[i],b[i],time);
k-=time;
}
ans+=k*(x1-1);
cout<<ans<<'\n';
}
}