11.7多校联考

T1

为了避免晚上种种事情导致写不成题解就先把T1写了,毕竟也是很值得写的。
我这道题凭着一个半感性半理性的想法意外的水到了80分……真的是很考人品啊【学竞赛啊,坠重要的就是人品!】
先看正解:
我们可以这样化:
T=(((sbk1+i1a)bk2+i2a)bk3+i3a)bk4+......
再化简一下:
T=sbk1+...+kn+i1abk2+...+kn+...+inabkn
所以我们可以在最外层枚举 k1+...+kn ,然后把剩余的值/a,开始递归,接着依次枚举 k2+...+kn,k3+...+kn,.....,kn 每次使它们的值尽量大,这样得到的加减次数就会尽量小了。

#include
#include
#include
using namespace std;
const int inf=1e9;
int s,t,a,b;
int mpow[30];
int solve(int x,int tmp)
{
    if(x==0) return 0;
    for(int i=tmp;i>=0;i--){
        if(mpow[i]>x) continue;
        for(int j=0;;j++){
            if(j*mpow[i]<=x&&(j+1)*mpow[i]>x) {
                int ret=solve(x-j*mpow[i],i);
                if(ret==-1) return -1;
                return ret+j;
            }
        }
    }   
}
int main()
{
    //freopen("a.in","r",stdin);
    //freopen("a.out","w",stdout);
    int ans=inf,cnt=0;
    scanf("%d%d%d%d",&s,&t,&a,&b);
    //T=s*b^(k1+....kn)+i1*a*b^(k2+....kn)+...+in*a*b^kn
    mpow[0]=1;
    for(int i=1;mpow[i-1]<=t;i++,cnt++) mpow[i]=mpow[i-1]*b;
    cnt--;
    for(int i=0;i<=cnt;i++){
        if((t-s*mpow[i])%a==0){
            int ret;
            ret=solve((t-s*mpow[i])/a,i);
            if(ret==-1) continue;
            ans=min(ans,i+ret);
        }
    }
    if(ans==inf) printf("-1");
    else printf("%d",ans);
    return 0;
}

我的那个诡异的方法是怎么回事晚上补

T3
易理解具有二分性质
易理解进行x轮操作,可以把小B的操作全部提到前面。
把每个数指向它应该在的位置,如果形成了一个环,那么环内交换的数一共只用“环内数字-1”
例:1 3 2 5 4

你可能感兴趣的:(------模拟考试-----)