T1.A
分析:
考试的时候,直接bfs(想都没想)
看一下官方题解吧:
一定要仔细读题解(特别是注意柿子的系数和下标)
注意m的表达式:
题解只是说要贪心的构造x,一开始我还是有点懵的
py了一下学长的代码,发现真的是贪心
注意:只有m为整数的时候才有一下的操作
我们确定了一个n之后,m中b的次方最大的就是n
我们就从b^n次方开始:tot+=m/b^n
b的次方逐次递减,不用担心m是否可以用这种方式拼出来(毕竟有b^0,不虚)
//这里写代码片
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#define ll long long
using namespace std;
const int INF=1e9+7;
ll S,T,a,b,n,m;
ll ans=0;
void solve()
{
ans=INF;
int nn=log(T/S)/log(b); //乘的最大次数
ll bb=1; //b^n
for (n=0;n<=nn;n++) //枚举乘的次数
{
ll t=T-bb*S;
if (t<0) break;
ll tot=0; //Σx
if (t%a==0) //只有m是整数的时候,有下述操作
{
m=t/a;
ll bx=bb;
while (m)
{
tot+=(m/bx);
m%=bx;
bx/=b;
}
ans=min(ans,tot+n);
}
bb*=b;
}
}
int main()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
scanf("%lld%lld%lld%lld",&S,&T,&a,&b);
if (S==T)
{
printf("0\n");
return 0;
}
solve();
if (ans==INF) printf("-1\n");
else printf("%d\n",ans);
return 0;
}
T2.B
T3.C
分析:
如果我们不考虑B
只有A一个人操作,那么事情会变成什么样呢
摆在我们面前的是一个序列
我们需要交换若干次使ta有序
这个时候,我的脑子里浮现了两个字:“置换”
还记得UVa11077这道题吗
实际上使序列有序就是一个置换
而这个置换可以看成是若干轮换的积
我们要通过乘上一些对换,使得这个置换变成n个轮换(仔细考虑一下)
也就是说,我们把当前序列变成若干轮换(一共X个)
则我们需要至少n-X次才能使序列有序
(因为长度为c的轮换需要c-1次交换)
所以我们二分一个答案mid
把B的操作都进行完之后,判断该置换需要的交换次数是否小于等于mid
一开始我打算一遍循环解决问题的,但是这样很容易就会失掉最优解
所以最保险的还是二分,并且把两个人的操作“分开”考虑
tip
二分对着样例调一调就好了,不要写死循环了
尽量不要用stl,慢的要死
//这里写代码片
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int N=200005;
int n,a[N];
int X[N<<1],Y[N<<1],fa[N],num[N<<1],cnt[N];
int find(int x)
{
if (fa[x]!=x) fa[x]=find(fa[x]);
return fa[x];
}
int pd(int mid)
{
for (int i=1;i<=n;i++) fa[i]=i,cnt[i]=0;
memcpy(num,a,sizeof(num));
for (int i=1;i<=mid;i++)
swap(num[X[i]],num[Y[i]]);
for (int i=1;i<=n;i++) //并查集维护环
{
int f1=find(i);
int f2=find(num[i]);
if (f1!=f2) fa[f2]=f1;
}
int tot=0;
for (int i=1;i<=n;i++)
{
int f1=find(i);
cnt[f1]++;
}
for (int i=1;i<=n;i++) if (cnt[i]) tot++;
tot=n-tot;
if (tot<=mid) return 1;
else return 0;
}
int solve()
{
int ans=0;
int L=0;
int R=2*n;
while (L<=R)
{
int mid=(L+R)/2;
if (pd(mid))
ans=mid,R=mid-1;
else L=mid+1;
}
return ans;
}
int main()
{
freopen("c.in","r",stdin);
freopen("c.out","w",stdout);
scanf("%d",&n);
bool ff=1;
for (int i=1;i<=n;i++)
{
scanf("%d",&a[i]); a[i]++;
if (a[i]!=a[i-1]+1) ff=0;
}
for (int i=1;i<=2*n;i++)
scanf("%d%d",&X[i],&Y[i]),X[i]++,Y[i]++;
if (ff) {printf("0\n");return 0;}
printf("%d",solve());
return 0;
}