Codeforces Round 885 (Div. 2) C. Vika and Price Tags

C. Vika and Price Tags

C - Vika and Price Tags

题意:

​ 初始两串数列a,b,对于第i个数,令ci=|aibi|,然后将数列a=b,b=c。重复这样的操作,问是否可能让a串全部变成0。

思路:

这题实际上之前已经发过,但最近打牛客对这题有了新的理解,所以来记录一下。

​ 让我们假设a>>b,那么我们模拟的过程就会变成如下这样:

(a,b)(b,ab)(ab,a2b)(a2b,b)(b,a3b)(a3b,a4b)(a4b,b)(b,a5b)(a5b,a6b)(a6b,b)(b,a7b)

​ 仔细观察可以发现,(akb,b)(b,atb)的结构在反复出现,且k一定为偶数,t一定为奇数。

​ 对于这种一个数不断地减去另一个数的形式,我们可以回想起,裴蜀定理得,a,b辗转相减只可能得到其gcd的若干倍(gcd辗转相除的原理)

​ 也即是说,对于(a,b)我们可以将其变成(a%b,b)/(b,a%b),记t=a/b

​ 对于t为奇数,(a,b)(b,a%b),次数为(t1)/23+1

​ 对于t为偶数,(a,b)(a%b,b),次数为t/23

int cal(int a, int b){
    if(a == 0){
        return 0;
    }
    else if(b == 0){
        return 1;
    }
    if(a >= b){
        int t = a / b;
        if(t % 2){
            return cal(b, a % b) + 1 + (t - 1) / 2 * 3;
        }
        else{
            return cal(a % b, b) + t / 2 * 3;
        }
    }
    else{
        return 1 + cal(b, abs(a - b));
    }
}
 
void QAQ(){
    int n;
    cin >> n;
    vector<int> a(n + 1), b(n + 1);
    for(int i = 1; i <= n; i ++) cin >> a[i];
    for(int i = 1; i <= n; i ++) cin >> b[i];
    set<int> s;
    for(int i = 1; i <= n; i ++){
        if(a[i] == 0 && b[i] == 0) continue;
        s.insert(cal(a[i], b[i]) % 3);
    }
    if(s.size() <= 1) cout << "YES" << endl;
    else cout << "NO" << endl;
}

裴蜀定理得,a,b辗转相减只可能得到其gcd的若干倍(gcd辗转相除的原理)

posted @   一棵木头罢辽  阅读(52)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示