J 模拟 T3 TLE 90 求助

神奇的,这次 test 8 TLE,但是其它 AC,,,

思路是因式定理,枚举常数项的全部因子,然后用类大除法的去降次。

#include <bits/stdc++.h>
using lint = long long;
using ull = unsigned long long;
using pii = std::pair<int, int>;
const int N = 20;
const int MOD[2] = {998244353, (int)1e9 + 7};

int n;
std::map<int, int> mp;
pii a[N]; // first:系数 second:指数
std::string str;

inline void split() {
  size_t lst = 0;
  size_t pos = std::min(str.find('+'), str.find('-'));

  while (pos != std::string::npos) {
    ++n;
    std::string s = str.substr(lst, pos - lst);

    size_t zhi = s.find('^');

    if (zhi != std::string::npos) {
      // ax^b
      if (s[0] == 'x') a[n].first = 1;
      else a[n].first = stoi(s.substr(0, zhi - 1));
      a[n].second = stoi(s.substr(zhi + 1));
    } else { // 指数为 1
      if (s[0] == 'x') a[n].first = 1;
      else a[n].first = stoi(s.substr(0, s.size() - 1));
      a[n].second = 1;
    }

    lst = pos;
    pos = std::min(str.find('+', lst + 1), str.find('-', lst + 1));
  }

  // 处理常数项
  a[++n].first = stoi(str.substr(lst));
  a[n].second = 0;

  // std::reverse(a + 1, a + n + 1);
}

inline lint qpow(lint a, lint b, int id) {
  lint res = 1;
  for (; b; b >>= 1) {
    if (b & 1) (res *= a) %= MOD[id];
    (a *= a) %= MOD[id];
  }
  return res;
}

inline lint calc(lint x, int id) {
  lint res = 0;
  for (int i = 1; i <= n; ++i) {
    (res += a[i].first * qpow(x, a[i].second, id) % MOD[id]) %= MOD[id];
  }
  return res;
}

inline ull qpow(ull a, lint b) {
  ull res = 1;
  for (; b; b >>= 1) {
    if (b & 1) res *= a;
    a *= a;
  }
  return res;
}

inline ull calc2(lint x) {
  ull res = 0;
  for (int i = 1; i <= n; ++i) {
    res += a[i].first * qpow(x, a[i].second);
  }
  return res;
}

inline bool check(lint x) { // 检查这个选项带入后是否可行
  return (calc(x, 0) == 0) && (calc(x, 1) == 0) && (calc2(x) == 0);
}

inline void work(lint t) { // 除法
  t = -t;
  // 全部除以 x + t
  for (int i = 1; i < n; ++i) {
    // 取出 x^{a[i].second - 1}
    a[i + 1].first -= a[i].first * t;
  }
  --n;
}

int main() {
  freopen("decompose.in", "r", stdin);
  freopen("decompose.out", "w", stdout);

  std::cin >> str;
  split(); // 将每一项分离

  auto t = abs(a[n].first);  
    
  while (n > 1) {

    for (lint i = 1; i <= t / i; ++i) {
      if (t % i) continue;
      // 存在 i, -i, a[1] / i, -a[1] / i 
      if (check(i)) {
        work(i);
        ++mp[-i];
        break;
      }
      if (check(-i)) {
        work(-i);
        ++mp[i];
        break;
      }
      if (check(t / i)) {
        work(t / i);
        ++mp[-t / i];
        break;
      }
      if (check(-t / i)) {
        work(-t / i);
        ++mp[t / i];
        break;
      }
    }
  }

  for (auto p : mp) {
    std::cout << "(x";
    if (p.first >= 0) std::cout << "+" << p.first << ")";
    else std::cout << p.first << ")";

    if (p.second > 1) std::cout << "^" << p.second;
  }

  std::cout << std::endl;

  return 0;
}
1 个赞

大佬能说一下思路吗,我就差这一题了,90分也好

1 个赞

dalao啊,我一点不会

1 个赞

@金杭东

因式定理:对于一个多项式 f(x) ,若 \exists\,t 使得 f(t)=0 ,那么 f(x) 必然有一个因式 (x-t)

因式定理的性质:若 f(t)=0 ,则 t 当且仅当是常数项的因数。

然后我就用字符串的一堆函数把输入给拆开,在最高次项次数 >1 的时候枚举常数项因数,然后用一个类似哈希的东西判断 f(t) 是否为 0 ,然后就用大除法一样的东西除掉 (x-t) 就行了。

2 个赞

看不懂的数学符号又增加了∃

1 个赞

这道题目光把输入拆开就很烦

2 个赞

想到有这个定理,但我的石山挂了(悲

石山又是什么东西

我的石山代码写了100行挂了

1 个赞

J组写出了S组的感觉

1 个赞

石山=屎山

我第四题是99行,笑

1 个赞

image

1 个赞

这题处理字符串我就打了好久(我是菜鸡

2 个赞

这题理论可以求导求出每个单调区间然后二分答案(doge

2 个赞

第 3 题写久了,第 4 题开题后只剩下 30 min 了,根本来不及写,于是随便胡了一个 DP 上去骗分

1 个赞

我跳过了第三题

1 个赞

你的策略是正确的,这题感觉比T4难打

1 个赞

存在的意思

2 个赞
#include <bits/stdc++.h>
using lint = long long;using ull = unsigned long long;using pii = std::pair<int, int>;const int N = 20;const int MOD[2] = {998244353, (int)1e9 + 7};int n;std::map<int, int> mp;pii a[N];std::string str;inline void split() {size_t lst = 0;size_t pos = std::min(str.find('+'), str.find('-'));while (pos != std::string::npos) {++n;std::string s = str.substr(lst, pos - lst);size_t zhi = s.find('^');if (zhi != std::string::npos) {if (s[0] == 'x') a[n].first = 1;else a[n].first = stoi(s.substr(0, zhi - 1));a[n].second = stoi(s.substr(zhi + 1));} else {if (s[0] == 'x') a[n].first = 1;else a[n].first = stoi(s.substr(0, s.size() - 1));a[n].second = 1;}lst = pos;pos = std::min(str.find('+', lst + 1), str.find('-', lst + 1));}a[++n].first = stoi(str.substr(lst));a[n].second = 0;}inline lint qpow(lint a, lint b, int id) {lint res = 1;for (; b; b >>= 1) {if (b & 1) (res *= a) %= MOD[id];(a *= a) %= MOD[id];}return res;}inline lint calc(lint x, int id) {lint res = 0;for (int i = 1; i <= n; ++i) {(res += a[i].first * qpow(x, a[i].second, id) % MOD[id]) %= MOD[id];}return res;}inline ull qpow(ull a, lint b) {ull res = 1;for (; b; b >>= 1) {if (b & 1) res *= a;a *= a;}return res;}inline ull calc2(lint x) {ull res = 0;for (int i = 1; i <= n; ++i) {res += a[i].first * qpow(x, a[i].second);}return res;}inline bool check(lint x) {return (calc(x, 0) == 0) && (calc(x, 1) == 0) && (calc2(x) == 0);}inline void work(lint t) { t = -t;for (int i = 1; i < n; ++i) {a[i + 1].first -= a[i].first * t;}--n;}int main() {freopen("decompose.in", "r", stdin);freopen("decompose.out", "w", stdout);std::cin >> str;split(); auto t = abs(a[n].first);  while (n > 1) {for (lint i = 1; i <= t / i; ++i) {if (t % i) continue;if (check(i)) {work(i);++mp[-i];break;}if(check(-i)) {work(-i);++mp[i];break;}if (check(t / i)) {work(t / i);++mp[-t / i];break;}if (check(-t / i)) {work(-t / i);++mp[t / i];break;}}}for (auto p : mp) {std::cout << "(x";if (p.first >= 0) std::cout << "+" << p.first << ")";else std::cout << p.first << ")";if (p.second > 1) std::cout << "^" << p.second;}std::cout << std::endl;return 0;}

帮你把代码优化了一下(短了1000B)

1 个赞