A-炼金术师
题意:
给一个序列,序列中的值代表一种颜色,从左到右每个元素都可以画[0,a[i]]区间的颜色,后面的会覆盖掉前面的颜色,而你可以每次选择[1,n]任意一个颜色和任意一个端点[0,r]进行画画。求最少次数画出来根序列一样的画布。
思路:因为每次后面的都会覆盖前面颜色,所以我们从后往前来考虑。实际上就是从后往前求一个递增序列。因为比后面数大的才不会被覆盖掉。
#include <bits/stdc++.h>
#define pb push_back//vector,deque
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N=1e6+5;
int a[N];
void solve()
{
int t;
cin>>t;
while(t--){
}
}
int main() {
// solve();
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
int res=0,sum=-1;
for(int i=n;i>=1;i--){
if(a[i]>sum){
res++;
sum=a[i];
// cout<<sum<<'\n';
}
}
printf("%d\n",res);
return 0;
}
同样也可以用栈来写。
#include <bits/stdc++.h>
#define pb push_back//vector,deque
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N=1e5+5;
void solve()
{
int t;
cin>>t;
while(t--){
}
}
int main() {
// solve();
int n,x;
cin>>n;
stack<int>s;
for(int i=1;i<=n;i++){
cin>>x;
while(s.size()&&s.top()<=x)s.pop();
s.push(x);
}
cout<<s.size()<<'\n';
return 0;
}
// 用栈比较容易出错的是没有+=,因为出现像 5 3 4 4 1这种情况是需要把第一个4弹出去的,不然只能过70%
B-刀工对决
bfsTLE了
#include <bits/stdc++.h>
#define pb push_back//vector,deque
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N=1e5+5;
struct node{
int a,b,step;
};
int bfs(int a,int b)
{
queue<node>q;
while(q.size())q.pop();
q.push({a,b,0});
while(q.size()){
node h=q.front();
q.pop();
if(h.a==h.b){
return h.step;
}
if(h.a>h.b){
if(h.a%5==0)q.push({h.a*3/5,h.b,h.step+1});
if(h.a%3==0)q.push({h.a/3,h.b,h.step+1});
}else{
if(h.b%5==0)q.push({h.a,h.b*3/5,h.step+1});
if(h.b%3==0)q.push({h.a,h.b/3,h.step+1});
}
}
return -1;
}
void solve()
{
int t,res=0;
bool flag=true;
int a,b;
cin>>t;
while(t--){
cin>>a>>b;
int temp=bfs(a,b);
res+=temp;
if(temp==-1){
flag=false;break;
}
// cout<<res<<'\n';
}
if(flag)cout<<res;
else cout<<-1;
cout<<'\n';
}
int main() {
solve();
return 0;
}
考虑先除5,然后不断除3
#include <bits/stdc++.h>
#define pb push_back//vector,deque
#define INF 0x3f3f3f3f
#define scd(n) scanf("%d",&n)
#define prd(n) printf("%d",n)
using namespace std;
typedef long long ll;
const int N=1e5+5;
void solve()
{
int t;
scd(t);
bool flag=true;
int res=0;
while(t--){
int a,b;
scd(a);scd(b);
if(!flag)continue;
int cnt1=0,cnt2=0;
while(a%5==0){
a/=5;
a*=3;
cnt1++;
}
while(b%5==0){
b/=5;
b*=3;
cnt2++;
}
res+=abs(cnt1-cnt2);
if(a>b){
while(a!=b&&a!=1){
a/=3;
res++;
}
}else{
while(a!=b&&b!=1){
b/=3;
res++;
}
}
if(a!=b){
flag=false;continue;
}
}
if(flag)prd(res);
else puts("-1");
puts("\n");
}
int main() {
solve();
return 0;
}
C-小G的GCD
题意:
gcd(x,y)被定义成求辗转相除的次数。而我们要做的是求max{gcd(i,j)}。给定n求最大的maxGCD。n<=1e18。
思路:打表找规律,最后发现竟然跟斐波那契数列有关hhh
#include <bits/stdc++.h>
#define pb push_back//vector,deque
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N=1e5+5;
ll f[100],res[100];
ll maxx=1e18;
void init()
{
f[1]=1;f[2]=1;
res[1]=1;res[2]=2;
for(int i=3;i<=86;i++){
f[i]=f[i-1]+f[i-2];
res[i]=f[i]+res[i-1];
}
// for(int i=1;i<=86;i++)cout<<res[i]<<'\n';
}
int main() {
// solve();
ll n,ans;
cin>>n;
init();
for(int i=1,j=2;i<=86;i++,j++){
if(res[i]>=n){
ans=j;break;
}
}
cout<<ans<<'\n';
return 0;
}
//1000000000000000000