zoukankan      html  css  js  c++  java
  • 牛客练习赛42D(性质、数学)

    题目传送

    就像题解所说的,写几个可以发现有分成四段的性质:第一段是从n开始往下贪,第二段是个数字,第三段……卧槽好吧真难描述。

    然后发现这个数据量可达1e9,所以考虑“二分确定序列+数学计算”的方式解题。

    首先二分出第一段的长度,这里我写得丑了,又将某些情况特判了一下;不难发现有了第一段的长度、N、K这三个量,序列已确定。

    然后疯狂手推数学公式把这四段的值求出来,特殊情况的例子很好举,自己调一调打打补丁做一做膜法,大概就莽A了吧……不过要是在考场上本垃圾就必死无疑了。

     1 #include <cstdio>
     2 #include <cmath>
     3 #include <iostream>
     4 using namespace std;
     5 
     6 typedef long long ll;
     7 const ll mod = 1e9 + 7;
     8 ll N, K, x, ans1, ans2, ans3, ans4;
     9 
    10 ll add(ll a, ll b) {
    11     return a + b >= mod ? a + b - mod : a + b;
    12 }
    13 
    14 ll sub(ll a, ll b) {
    15     return a - b < 0 ? a - b + mod : a - b;
    16 }
    17 
    18 ll ksm(ll a, ll b) {
    19     ll ret = 1;
    20     for (; b; b >>= 1) {
    21         if (b & 1)    ret = ret * a % mod;
    22         a = a * a % mod;
    23     }
    24     return ret;
    25 }
    26 
    27 inline ll cal(ll l, ll r) {
    28     return (l + r) * (r - l + 1) / 2;
    29 }
    30 
    31 inline ll cal2(ll n) {//这是求x + 2*x^2 + ... + n*x^n的函数
    32     ll a = n % mod * ksm(x, n + 1) % mod * (x - 1) % mod;
    33     ll b = x * sub(ksm(x, n), 1) % mod;
    34     return sub(a, b) * ksm((x - 1) * (x - 1) % mod, mod - 2) % mod;
    35 }
    36 
    37 int main() {
    38     cin >> N >> K;
    39     x = N + 1;
    40     if (K == 0) {
    41         cout << cal2(N) << endl;
    42         return 0;
    43     }
    44     ll l = 1, r = N;
    45     while (l < r) {
    46         ll mid = (l + r) >> 1;
    47         if (cal(N - mid, N - 1) <= K)    l = mid + 1;
    48         else    r = mid;
    49     }
    50     while (cal(N - l, N - 1) >= K)    l--;//至此l为第一段长度。如果出现54312这种,会将54作为第一段,3作为第二段,12为第三段,第四段为空
    51     if (l) {
    52         ans1 = add(sub(x * x % mod * (ksm(x, l) - 1 + mod) % mod * ksm(x - 1, mod - 2) % mod, l * x % mod), (N - l) * x % mod * (ksm(x, l) - 1 + mod) % mod) * ksm(x - 1, mod - 2) % mod;
    53         K -= cal(N - l, N - 1);
    54     }
    55     if (K) {
    56         K++, l++;//K就是第二段那个数字,l++只是为了运算简便
    57         ans2 = K % mod * ksm(x, l) % mod;
    58         ans3 = ksm(x, l) * cal2(K - 1) % mod;
    59         if (N - l + 1 > K) {//如果有第四段
    60             ll tmp = K % mod * sub(ksm(x, N + 1), ksm(x, K + l)) % mod * ksm(x - 1, mod - 2) % mod;
    61             ans4 = add(tmp, ksm(x, K + l - 1) * cal2(N - K - l + 1) % mod);
    62         }
    63     }
    64     cout << (ans1 + ans2 + ans3 + ans4) % mod;
    65     return 0;
    66 }
  • 相关阅读:
    std thread
    windows更新包发布地址
    How to set up logging level for Spark application in IntelliJ IDEA?
    spark 错误 How to set heap size in spark within the Eclipse environment?
    hadoop 常用命令
    windows 安装hadoop 3.2.1
    windows JAVA_HOME 路径有空格,执行软连接
    day01MyBatisPlus条件构造器(04)
    day01MyBatisPlus的CRUD 接口(03)
    day01MyBatisPlus入门(02)
  • 原文地址:https://www.cnblogs.com/AlphaWA/p/10551433.html
Copyright © 2011-2022 走看看