結果

問題 No.1276 3枚のカード
ユーザー logxlogx
提出日時 2020-09-16 19:28:21
言語 C++14
(gcc 13.2.0 + boost 1.83.0)
結果
AC  
実行時間 316 ms / 2,000 ms
コード長 9,561 bytes
コンパイル時間 2,248 ms
コンパイル使用メモリ 188,044 KB
実行使用メモリ 6,648 KB
最終ジャッジ日時 2023-09-04 03:48:36
合計ジャッジ時間 14,100 ms
ジャッジサーバーID
(参考情報)
judge12 / judge13
このコードへのチャレンジ(β)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
4,384 KB
testcase_01 AC 1 ms
4,380 KB
testcase_02 AC 2 ms
4,380 KB
testcase_03 AC 2 ms
4,380 KB
testcase_04 AC 2 ms
4,376 KB
testcase_05 AC 2 ms
4,376 KB
testcase_06 AC 1 ms
4,380 KB
testcase_07 AC 2 ms
4,376 KB
testcase_08 AC 2 ms
4,380 KB
testcase_09 AC 2 ms
4,380 KB
testcase_10 AC 271 ms
5,964 KB
testcase_11 AC 138 ms
4,552 KB
testcase_12 AC 172 ms
4,896 KB
testcase_13 AC 179 ms
5,056 KB
testcase_14 AC 22 ms
4,376 KB
testcase_15 AC 147 ms
4,880 KB
testcase_16 AC 293 ms
6,120 KB
testcase_17 AC 168 ms
4,880 KB
testcase_18 AC 131 ms
4,624 KB
testcase_19 AC 203 ms
5,084 KB
testcase_20 AC 125 ms
4,728 KB
testcase_21 AC 129 ms
4,660 KB
testcase_22 AC 298 ms
6,112 KB
testcase_23 AC 19 ms
4,376 KB
testcase_24 AC 192 ms
5,092 KB
testcase_25 AC 73 ms
4,376 KB
testcase_26 AC 234 ms
5,740 KB
testcase_27 AC 265 ms
5,936 KB
testcase_28 AC 256 ms
6,032 KB
testcase_29 AC 156 ms
5,052 KB
testcase_30 AC 37 ms
4,376 KB
testcase_31 AC 19 ms
4,376 KB
testcase_32 AC 77 ms
4,376 KB
testcase_33 AC 8 ms
4,376 KB
testcase_34 AC 56 ms
4,380 KB
testcase_35 AC 53 ms
4,376 KB
testcase_36 AC 6 ms
4,380 KB
testcase_37 AC 49 ms
4,376 KB
testcase_38 AC 36 ms
4,376 KB
testcase_39 AC 81 ms
4,380 KB
testcase_40 AC 287 ms
5,964 KB
testcase_41 AC 241 ms
5,932 KB
testcase_42 AC 258 ms
5,948 KB
testcase_43 AC 229 ms
5,648 KB
testcase_44 AC 313 ms
6,132 KB
testcase_45 AC 287 ms
6,648 KB
testcase_46 AC 286 ms
6,532 KB
testcase_47 AC 241 ms
6,080 KB
testcase_48 AC 232 ms
5,828 KB
testcase_49 AC 260 ms
5,924 KB
testcase_50 AC 285 ms
5,916 KB
testcase_51 AC 247 ms
5,928 KB
testcase_52 AC 216 ms
5,664 KB
testcase_53 AC 249 ms
5,992 KB
testcase_54 AC 284 ms
5,864 KB
testcase_55 AC 223 ms
5,584 KB
testcase_56 AC 218 ms
5,664 KB
testcase_57 AC 272 ms
5,920 KB
testcase_58 AC 282 ms
5,912 KB
testcase_59 AC 250 ms
5,864 KB
testcase_60 AC 316 ms
6,116 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <bits/stdc++.h>
#ifndef ONLINE_JUDGE
#define _GLIBCXX_DEBUG
#endif
using namespace std;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define rep2(i, s, n) for (int i = s; i < (int)(n); i++)
#define Clear(a) a = decltype(a)()
#define all(a) a.begin(),a.end()
#define rall(a) a.rbegin(),a.rend()
#define vec vector
typedef long long ll;
typedef pair<ll,ll> P;
//const ll big=998244353;
const ll big=1000000007LL;
const ll INF=1e18;
const int dx[4]={1,0,-1,0};
const int dy[4]={0,1,0,-1};
ll max(ll x,ll y){
    if(x>y)return x;
    else return y;
}
ll min(ll x,ll y){
    if(x<y)return x;
    else return y;
}
ll expm(ll x,ll y){
    if(y==0)return 1;//0^0=1
    if(x==1||x==0)return x;
    if(y%2==1)return (expm(x,y-1)*x)%big;
    ll t=expm(x,y/2);
    return (t*t)%big;
}
ll exp(ll x,ll y){
    if(y==0)return 1;//0^0=1
    if(x==1||y==0)return x;
    if(y%2==1)return exp(x,y-1)*x;
    ll t=exp(x,y/2);
    return t*t;
}

//約数和のためのやつ
#define u64 unsigned long long
#define u32 unsigned
 
struct u128 {
  u64 l;
  u64 h;
  u128() : l(0), h(0) {}
  u128(u64 l) : l(l), h(0) {}
  u128(u64 l, u64 h) : l(l), h(h) {}
 
  static u128 mul64(u64 a, u64 b) {
    u32 a_hi = a >> 32, a_lo = u32(a);
    u32 b_hi = b >> 32, b_lo = u32(b);
    u64 p0 = (u64)(a_lo) * b_lo;
    u64 p10 = (u64)(a_hi) * b_lo + (p0 >> 32);
    u64 p11 = (u64)(a_lo) * b_hi + p10;
    u64 p2 = ((u64)(p11 < p10) << 32) + (u64)(a_hi) * b_hi + (p11 >> 32);
    return u128(u32(p0) | (p11 << 32), p2);
  }
 
  static void divmod(u128 a, u32 d, u128& q, u32& r) {
    u32 a3 = a.h >> 32, a2 = a.h;
    u32 a1 = a.l >> 32, a0 = a.l;
 
    u64 t = a3;
    u32 q3 = t / d; t = ((t % d) << 32) | a2; 
    u32 q2 = t / d; t = ((t % d) << 32) | a1;
    u32 q1 = t / d; t = ((t % d) << 32) | a0;
    u32 q0 = t / d; r = t % d;
    q = u128(q0 | ((u64)(q1) << 32), q2 | ((u64)(q3) << 32));
  }
  bool is_zero() const {
    return l == 0 && h == 0;
  }
  bool operator >= (const u128& rhs) const {
    return h > rhs.h || (h == rhs.h && l >= rhs.l);
  }
  u128& operator += (const u64 rhs) {
    u64 old_l = l;
    l += rhs;
    h += (l < old_l);
    return *this;
  }
  u128& operator += (const u128& rhs) {
    u64 old_l = l;
    l += rhs.l;
    h += (l < old_l) + rhs.h;
    return *this;
  }
  u128& operator -= (const u128& rhs) {
    u64 old_l = l;
    l -= rhs.l;
    h -= (l > old_l) + rhs.h;
    return *this;
  }
  u128 operator + (const u64 rhs) const {
    return u128(*this) += rhs;
  }
  u128 operator + (const u128& rhs) const {
    return u128(*this) += rhs;
  }
  u128 operator - (const u128& rhs) const {
    return u128(*this) -= rhs;
  }
  std::string to_string() const {
    static const u32 ten9 = u32(1e9);
    if (is_zero()) {
      return "0";
    }
    char str[41];
    int i = 0;
 
    u128 n = *this;
    u32 r;
    while (1) {
      divmod(n, ten9, n, r);
      if (n.is_zero()) {
        while (r > 0) str[i++] = r % 10, r /= 10;
        break;
      } else {
        for (int j = 0; j < 9; ++j) str[i++] = r % 10, r /= 10;
      }
    }
    std::string ret;
    while (i) ret += '0' + str[--i];
    return ret;
  }
};
 
u32 isqrt(u64 n) {
  if (n >= (u64)(UINT32_MAX) * UINT32_MAX) {
    return UINT32_MAX;
  } else {
    u32 ret = sqrtl(n);
    assert((u64)(ret) * ret <= n);
    assert((u64)(ret + 1) * (ret + 1) > n);
    return ret;
  }
}
 
inline u64 div64_32(u64 a, u32 b) {
  u32 r, ql, qh;
  u32 al = a, ah = a >> 32;
  qh = ah / b; ah %= b;
  __asm__ (
    "divl %4\n\t"
    : "=a"(ql), "=d"(r)
    : "0"(al), "1"(ah), "rm"(b)
  );
  return ((u64)(qh) << 32) | ql;
}
 
ll sigma0_sum(ll n) {
  // 1 から N までの約数の個数の総和を返す。
  // 計算量: O(n^(1/3+))
  u64 N=(u64)(n);
  const u32 v = isqrt(N);
  const u32 w = pow(N, 0.35);
 
  u64 x = N / v;
  u32 y = N / x + 1;
 
  std::stack< std::pair<u32, u32> > stac;
  stac.emplace(1, 0);
  stac.emplace(1, 1);
 
  auto outside = [N] (u64 x, u32 y) {
    return x * y > N;
  };
 
  auto cut_off = [N] (u64 x, u32 ldx, u32 ldy) {
    return u128::mul64(x, x * ldy) >= u128::mul64(N, ldx);
  };
 
  u128 ret = 0;
  while (1) {
    u32 ldx, ldy;
    std::tie(ldx, ldy) = stac.top(); stac.pop();
 
    while (outside(x + ldx, y - ldy)) {
      ret += x * ldy + (u64)(ldy + 1) * (ldx - 1) / 2;
      x += ldx; y -= ldy;
    }
 
    if (y <= w) {
      break;
    }
 
    u32 udx = ldx, udy = ldy;
    while (1) {
      std::tie(ldx, ldy) = stac.top();
      if (outside(x + ldx, y - ldy)) break;
      udx = ldx, udy = ldy;
      stac.pop();
    }
 
    while (1) {
      u32 mdx = ldx + udx;
      u32 mdy = ldy + udy;
      if (outside(x + mdx, y - mdy)) {
        ldx = mdx, ldy = mdy;
        stac.emplace(ldx, ldy);
      } else {
        if (cut_off(x + mdx, ldx, ldy)) {
          break;
        }
        udx = mdx, udy = mdy;
      }
    }
  }
  for (u32 i = y - 1; i > 0; --i) {
    ret += div64_32(N, i);
  }
  ret = ret + ret - (u64)(v) * v;
  return stoll(ret.to_string().c_str());
}



template <ll mod> struct Fp{
    ll x;
    constexpr Fp(ll x=0) noexcept : x ((x%mod+mod)%mod){}
    /*-------ここから演算子-------*/
    constexpr Fp operator-() const noexcept{
        return Fp(-x);
    }
    constexpr Fp& operator+=(const Fp &a) noexcept{
        if((x+=a.x)>=mod)x-=mod;
        return *this;
    }
    constexpr Fp& operator-=(const Fp &a) noexcept{
        if((x+=mod-a.x)>=mod)x-=mod;
        return *this;
    }
    constexpr Fp& operator*=(const Fp &a) noexcept{
        (x*=a.x)%=mod;
        return *this;
    }
    constexpr Fp& operator/=(const Fp &a) noexcept{
        return (*this)*=a.inv();
    }
    constexpr Fp operator+(const Fp &a)const noexcept{
        Fp res(*this);
        return res+=a;
    }
    constexpr Fp operator-(const Fp &a)const noexcept{
        Fp res(*this);
        return res-=a;
    }
    constexpr Fp operator*(const Fp &a)const noexcept{
        Fp res(*this);
        return res*=a;
    }
    constexpr Fp operator/(const Fp &a)const noexcept{
        Fp res(*this);
        return res/=a;
    }

    constexpr bool operator==(const Fp &a)const noexcept{
        if((*this).x==a.x)return true;
        else return false;
    }
    constexpr bool operator!=(const Fp &a)const noexcept{
        return !((*this)==a);
    }
    constexpr bool operator<(const Fp &a)const noexcept{
        if((*this).x<a.x)return true;
        else return false;
    }
    constexpr bool operator>(const Fp &a)const noexcept{
        if((*this).x>a.x)return true;
        else return false;
    }
    constexpr bool operator<=(const Fp &a)const noexcept{
        return !((*this)>a);
    }
    constexpr bool operator>=(const Fp &a)const noexcept{
        return !((*this)<a);
    }
    /*-------ここまで演算子-------*/

    constexpr Fp pow(const ll &t)const noexcept{
        if(t==0)return (Fp)1;
        if(t%2==0){
            Fp k=pow(t/2);
            return k*k;
        }else{
            if(t>0)return (*this)*pow(t-1);
            else return pow(t+1)/(*this);
        }
    }
    constexpr Fp inv()const noexcept{
        return (Fp)forinv((*this).x,mod).first;
    }


    friend ostream& operator<<(ostream &os,const Fp &m)noexcept{
        os << m.x;
        return os;
   }
    friend istream& operator>>(istream &is,Fp &m)noexcept{
        is >> m.x;
        m.x%=mod;
        if(m.x<0)m.x=(m.x+mod)%mod;
        return is;
    }

private:
    //Euclidの互除法
    constexpr pair<ll,ll> forinv(ll a,ll b)const noexcept{
        if(b==0)return pair<ll,ll>(1,0);

        pair<ll,ll> ans = forinv(b,a%b);
        pair<ll,ll> t=pair<ll,ll>(ans.second,ans.first-a/b*ans.second);
        return t;
    }
};

using mint=Fp<big>;

mint fi(ll x){
    //約数の個数関数
    map<ll,ll> primes;
    for(ll p=2;p*p<=x;p++){
        if(x%p==0){
            while(x%p==0){
                x/=p;
                primes[p]++;
            }
        }
    }
    if(x!=1)primes[x]++;
    mint res=1;
    for(auto p : primes){
        res*=(p.second+1);
    }
    return res;
}
mint f(ll x){//非 約数の個数関数
    return (mint)x-fi(x);
}

int main(){
    ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    cout << fixed << setprecision(10);
    /*--------------------------------*/
    
    ll n;cin >> n;
/*  //愚直解
    mint ans=-(n+1)*n;
    rep2(i,1,n+1){
        ans+= -fi(i)*(n/i) - (n/i)*(n/i) + (n/i)*(n+3);
    }
    cout << ans << endl;*/

    mint cnt=-n*(n+1);

    //vector<pair<ll,ll>> で√nくらいの個数,[何回現れるか , 値]を持っておく→sum([n/i]) 1 to k(k<=√nくらい?)も前計算しておきたいかも…?
    vector<pair<ll,ll>> noveri;
    int s=1;
    while(s<=n){
        pair<ll,ll> ne={0,n/s};
        ll k=n/s;
        if(k==1){ne.first=n-n/2;noveri.push_back(ne);break;}
        ne.first=n/k - n/(k+1);
        noveri.push_back(ne);
        s=(n+k)/k;//(n+1)/kの切り上げ
    }
    //次に個数の累積和みたいなやつを作る
    vector<ll> sum;
    sum.push_back(0);
    rep(i,noveri.size()){
        sum.push_back(sum[i] + noveri[i].first );//sum[i]=Σnoveri[j] ,j=0 to i-1
    }

    rep(k,noveri.size()){
        ll num=noveri[k].first;//その値を取る個数
        ll val=noveri[k].second;//その時見ている[n/i]の値
        cnt+=(-(mint)val*val+(mint)(n+3)*val)*num;
        //[n/i]の値を取る間のσ(i)の和

        if(k==0)cnt-=(mint)sigma0_sum(sum[k+1]) * (mint)val;
        else cnt-=(mint)(sigma0_sum(sum[k+1])- sigma0_sum(sum[k]))*(mint)val;
    }
    cout << cnt << endl;
}
0