CodeForces 1105C 千万不要错过!! 最快解法

正解是 dp做 但是 速度 是 O(n)
我这么做 速度 是 log(n)
所以 正解 的 n的 只是 1 到 2e5
而我这么解
只要n 不超过 long 类型 都能秒出 !!!
过程 就不讲了 有点麻烦 反正就是 快…

#include <iostream>
using namespace std;
// 这里的 san 主要是 因为涉及 除法取 mod 所以事先求了一下 3 对 1e9 + 7的逆元 
#define san 333333336
typedef long long ll;
const ll mod = 1e9 + 7;
ll quick(ll a, ll b) {
    ll ans = 1;
    while (b) {
        if (b & 1) {
            ans = (ans * a) % mod;
        } 
        a = (a * a) % mod; 
        b >>= 1;
    }
    return ans;
}
ll cheng(ll a, ll b) {
    ll ans = 0;
    while (b) {
        if (b & 1) {
            ans = (ans + a) % mod;
        } 
        a = (a + a) % mod; 
        b >>= 1;
    }
    return ans;
    
}
int main() {
    long long n, l, r;
    cin >> n >> l >> r;
    // 先考虑 不足三个的时候.. 
    if (l == r) {
        cout << ((l * n) % 3 == 0)<< endl;
        return 0; 
    }
    if (r - l == 1) {
        if (n == 1) {
            cout <<(l % 3 != 1)<< endl;
            return 0;
        }ll ans;
        if (l % 3 == 1) {
            ans = 2;
            int jia[2] = {2, -2};
            for (int i = 3; i <= n; i++) {
                ans = (ans * 2 + jia[i % 2]) % mod;
            }
        } else {
            ans = 1;
            int jia[6] = {0, -1, -1, 0, 1, 1};
            for (int i = 3; i <= n; i++) {
                ans = (ans * 2 + jia[i % 6]) % mod;
            }
        }
        cout << ans << endl;
        return 0;
    }
    // 接下来考虑 三种情况
    //  1 正常情况 即 开始的 数 对三取余之后 0, 1, 2 的数量相等 
    if (l % 3 == (r + 1) % 3) {
        ll x = quick(r - l + 1, n - 1);
        ll a = (r - l + 1) / 3;
        a %= mod;
        cout << (x * a) % mod << endl;
        return 0; 
    }
    // 考虑 有一种某数多了一个的情况 这种情况 又分两种 (有个现象 谁多一谁一定是开头 -- l) 
// 第一种 0 的数量多一  
   if (l % 3 == 0 && r % 3 == 0) {
       ll x = quick(r - l + 1, n - 1);
       ll a = (r - l + 1) / 3;
       // 由于 这里 的 3 * a * x 有可能爆long long; 
//       cout << ((3 * a * x + x + 2) * san) % mod << endl;
// 所以我决定 写一个乘法 取余保证不爆 long long; 
      cout << (((cheng(3 * a, x) + x + 2) % mod) * san) % mod << endl;
      return 0;
   }
 // 第二种 1 或 2 的数量多一 (这里 1 或 2 的数量不管谁多一 结果都一样 ) 
   if (l % 3 != 0 && l % 3 == r % 3) {
       ll x = quick(r - l + 1, n - 1);
       ll a = (r - l + 1) / 3;
       if ((n - 1) % 3 != 2) 
    cout << (((cheng(3 * a, x) + x - 1) % mod) * san) % mod << endl;
    else 
    cout << (((cheng(3 * a, x) + x + 2) % mod) * san) % mod << endl;
   } 
   // 考虑 第三种 情况 某两个数 的数量多一  比如 12 多一 20 多一 或 01多一
   // 这也要分两种情况考虑
   // 第一种 12 的数量多一
   if (l % 3 == 1 && r % 3 == 2) {
    ll x = quick(r - l + 1, n - 1);
    ll a = (r - l + 1)/3;
    if ((n - 1) % 2) {
        cout << (((cheng(3 * a, x) + cheng(2, x) + 2) % mod) * san) % mod << endl;
    } else {
        cout << (((cheng(3 * a, x) + cheng(2, x) - 2) % mod) * san) % mod << endl;
    }
       
   } 
   // 第二种 20 或 01 多 
   // 这种 情况 有点复杂 分七种情况考虑 
   if (l % 3 != 1 && l % 3 == (r - 1) % 3) {
   ll x = quick(r - l + 1, n - 1);
   ll a =((r - l) / 3) % mod;
   if ((n - 1) % 6 == 1 || (n - 1) % 6 == 3) {
       cout << (((cheng(3 * a, x) + cheng(2, x) - 1) % mod) * san) % mod << endl;
   } else if ((n - 1) % 6 == 2) {
       cout << (((cheng(3 * a, x) + cheng(2, x) - 2) % mod) * san) % mod << endl;
   } else if ((n - 1) % 6 == 4 || (n - 1) % 6 == 0) {
       cout << (((cheng(3 * a, x) + cheng(2, x) + 1) % mod) * san) % mod << endl;
   } else if ((n - 1) % 6 == 5) {
       cout << (((cheng(3 * a, x) + cheng(2, x) + 2) % mod) * san) % mod << endl;
   }
   }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值