A 當b>2*a時每次只減一個數會花費更少,否則先同減到其中一個數爲0再計算會更少。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=200010;
int t,n,m;
ll x,y,a,b;
int main()
{
cin>>t;
while(t--)
{
cin>>x>>y>>a>>b;
ll ans=0;
ans+=min(x,y)*b;
ans+=(max(x,y)-min(x,y))*a;
cout<<min(ans,(x+y)*a)<<endl;
}
return 0;
}
B 如果t中只有一種字符那麼它的週期k就是1已經最小了直接輸出,否則週期不可能爲1,但是週期爲2是一定構造出來的,01交替即可,所以將相鄰的兩個相同字符中間加一個其他字符就可以了。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1010;
int t,n,m;
string s,st;
int main(){
cin>>t;
while(t--){
cin>>s;
bool flag=1;
for(int i=0;i<s.size()-1;i++)
if(s[i]!=s[i+1])
{
flag=0;
break;
}
if(!flag)
{
for(int i=0;i<s.size();i++)
if(i<s.size()-1)
{
st.push_back(s[i]);
if(s[i]==s[i+1])
{
if(s[i]=='1') st.push_back('0');
else st.push_back('1');
}
}
else st.push_back(s[i]);
cout<<st<<endl;
st.clear();//記得清空
}
else cout<<s<<endl;
}
return 0;
}
C 統計再區間[li,ri]之間x的個數,x滿足的條件是( (x%b)%a) != ( (x%a)%a)。
可以打表找規律:令Max=max(a,b),Lcm=lcm(a,b) , 滿足條件的x都有一個共性
x%Lcm在區間 [Max,Lcm)內。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1010;
int t,n,m,a,b;
string s,st;
ll get(ll l,int x,int y)//統計1到l滿足條件的個數
{
return l/y*(y-x)+max(0ll,l%y-x+1);
}
int main(){
cin>>t;
while(t--){
cin>>a>>b>>n;
int x=max(a,b),y=a*b/__gcd(a,b);
while(n--)
{
ll l,r;
cin>>l>>r;
cout<<get(r,x,y)-get(l-1,x,y)<<endl;
}
}
return 0;
}
D 又是一道閱讀理解。已知一個測試樣例有n個數組,每個數組的長度不超過k,第i數組的長度是mi,讓你把這一個測試樣例分成多個,每個樣例中長度大於等於i的數組數量不超過ci。
因爲ci統計的是大於等於,所以先放長度最大的數組,這樣放的時候已經放過的數組長度一定大於等於當前數組,所以當放第i個數組時如果樣例中的數組數量a大於等於c[m[i]]時就不能放到這個樣例了,因爲放進去後大於等於m[i]的數量就是a+1一定大於等於c[m[i]]了,不滿足題意。
還要使測試樣例儘可能的少,所以就要讓每個樣例裏面儘可能多,但是會有一個最大限制c[1],因爲所有數組長度一定大於等於1,所以每個樣例最多有c[1]個數組。
每個樣例儘可能得多放,所以遍歷ans個樣例找第一個滿足(數組數量小於c[m[i]])的樣例,將m[i]放進去,如果找不到就再開一個樣例。暴力去找的話肯定會超時,我們每次都放到第一個滿足的樣例,所以前面的樣例數組會最多,後面的樣例數組會少,就是說數組數量是單減的,再單減序列中找第一個小於某個數的位置可以用二分,num[i]統計第i個樣例中數組數量的負值,找第一個大於 -c[m[i]]的位置就可以了,如果超出ans,就再加一個樣例。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=200010;
int t,n,k,a,b;
int c[N],m[N];
vector<int> ve[N];
int num[N];
int ans=1;
int main(){
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++) scanf("%d",m+i);
for(int i=1;i<=k;i++) scanf("%d",c+i);
sort(m+1,m+n+1);
int l=1;//l表示還能放數組的最小樣例
for(int i=n;i;i--)//倒序枚舉先放最大的
{
int x=upper_bound(num+l,num+ans+2,-c[m[i]])-num;//num[ans+1]=0,可以直接二分
if(x<=ans)
{
ve[x].push_back(m[i]);
num[x]--;
if(ve[x].size()==c[1]) l=x+1;//最多可以放c[1]個
}
else ve[++ans].push_back(m[i]),num[x]--;
}
printf("%d\n",ans);
for(int i=1;i<=ans;i++)
{
printf("%d ",ve[i].size());
for(int j=0;j<ve[i].size();j++)
printf("%d ",ve[i][j]);
puts("");
}
return 0;
}