Reading

CodeForces 1558B Up the Strip


Fanyi Pu

ๆœ‰ n(2โ‰คnโ‰ค4โ‹…106) ไธช่Š‚็‚น๏ผŒ็ผ–ๅท 1โˆผn๏ผŒไฝ ไธ€ๅผ€ๅง‹ๅœจ่Š‚็‚น n๏ผŒๆƒณ่ฆๅˆฐ่Š‚็‚น 1ใ€‚ๅ‡่ฎพไฝ ็Žฐๅœจๅœจ่Š‚็‚น x๏ผŒไฝ ๅฏไปฅ่ฟ›่กŒไปฅไธ‹ไธค็งๆ“ไฝœ๏ผš

  1. ้€‰ๆ‹ฉไธ€ไธชๆญฃๆ•ดๆ•ฐ yโˆˆ[1,xโˆ’1]๏ผŒๅนถ็งปๅŠจๅˆฐ่Š‚็‚น xโˆ’yใ€‚
  2. ้€‰ๆ‹ฉไธ€ไธชๆญฃๆ•ดๆ•ฐ zโˆˆ[2,x]๏ผŒๅนถ็งปๅŠจๅˆฐ่Š‚็‚น โŒŠxzโŒ‹ใ€‚

ๆฑ‚ๆœ‰ๅคšๅฐ‘็งๆ–นๆกˆๅˆฐ่พพ่Š‚็‚น 1๏ผŒๅช่ฆๆœ‰ไธ€ๆฌก้€‰ๆ‹ฉ็š„ x ๆˆ– z ไธๅŒๅฐฑ็ฎ—ๆ–นๆกˆไธๅŒใ€‚็ญ”ๆกˆๅฏน m ๅ–ๆจก๏ผŒๅ…ถไธญ mโˆˆ(108,109) ไธ” m ๆ˜ฏ็ด ๆ•ฐใ€‚

ไปค fi ่กจ็คบ n=i ๆ—ถ็š„็ญ”ๆกˆ๏ผŒๆˆ‘ไปฌๆœ‰๏ผš

fi=โˆ‘j=1iโˆ’1fj+โˆ‘d=2ifโŒŠidโŒ‹

ๅ‰ไธ€้ƒจๅˆ†่กจ็คบ็”จๅ‡ๆณ•๏ผŒๅŽไธ€้ƒจๅˆ†่กจ็คบ็”จ้™คๆณ•ใ€‚

่€ƒ่™‘ไผ˜ๅŒ–๏ผŒ็ฌฌไธ€้ƒจๅˆ†็›ดๆŽฅๅ‰็ผ€ๅ’Œ๏ผŒๆˆ‘ไปฌ็›ดๆŽฅ่€ƒ่™‘็ฌฌไบŒ้ƒจๅˆ†ใ€‚ไธ€็งๅพˆ็›ดๆŽฅ็š„ไผ˜ๅŒ–ๆ˜ฏๅฐ†ๅฐไบŽ i ็š„ d ็›ดๆŽฅๆ‹ฟๅ‡บๆฅ็ฎ—๏ผŒๅคงไบŽ i ็š„ d ๆ‹ฟๅ‡บๆฅ็ฎ—่ดก็Œฎ๏ผŒ fk ่ƒฝ่ฝฌ็งปๅˆฐ fi ็š„ d ๅบ”่ฏฅๆปก่ถณ kโ‰คid<k+1๏ผŒไนŸๅณ ik+1<dโ‰คik๏ผŒไบŽๆ˜ฏ fk ๅฏน fi ็š„่ดก็Œฎๅบ”่ฏฅไธบ โŒŠnkโŒ‹โˆ’โŒŠnk+1โŒ‹ใ€‚่ฟ™ๆ ทๅšๅคๆ‚ๅบฆๆ˜ฏ O(nn)๏ผŒ่ฟ‡ไธๅŽป๏ผŒไฝ†ๆ˜ฏๅฆ‚ๆžœไฝ ๆ‰“ Div. 2 ็š„่ฏๅฐฑ่ƒฝ่ฟ‡ไธ€ไธช easy ็‰ˆใ€‚

ๆˆ‘ไปฌ่€ƒ่™‘ๆขไธ€็งๆ–นๅผ๏ผŒ่€ƒ่™‘ fi ่ฝฌ็งปๅˆฐ fi+1๏ผŒๆˆ‘ไปฌๆฏ”่พƒ โˆ‘d=2ifโŒŠidโŒ‹ ไธŽ โˆ‘d=2i+1fโŒŠi+1dโŒ‹๏ผŒๆœ‰ๅฆ‚ไธ‹ๅ˜ๅŒ–๏ผš

  1. ๅคšไบ†ไธ€ไธช f1๏ผŒๅ› ไธบ d ๅฏไปฅ็ญ‰ไบŽ i+1ใ€‚
  2. ๅฏนไบŽๆ‰€ๆœ‰ dโˆฃi+1๏ผŒโŒŠi+1dโŒ‹=โŒŠidโŒ‹+1๏ผŒๆ‰€ไปฅ fi+1 ๆฏ” fi ๅคšไบ†ไธ€ไธช fโŒŠi+1dโŒ‹๏ผŒๅฐ‘ไบ†ไธ€ไธช fโŒŠidโŒ‹ใ€‚

ไนŸๅฐฑๆ˜ฏ่ฏด๏ผš

fi+1=โˆ‘j=1ifj+โˆ‘d=2i+1fโŒŠi+1dโŒ‹=fi+โˆ‘j=1iโˆ’1fj+โˆ‘d=2i+1fโŒŠi+1dโŒ‹=fi+fi+f1+โˆ‘dโˆฃi+1(fโŒŠi+1dโŒ‹โˆ’fโŒŠidโŒ‹)=2fi+f1+โˆ‘dโˆฃi+1(fโŒŠi+1dโŒ‹โˆ’fโŒŠidโŒ‹)

ๆˆ‘ไปฌๅ‘็ŽฐๅฏนไบŽๆ‰€ๆœ‰ i๏ผŒๆ€ป็š„็บฆๆ•ฐไธชๆ•ฐไธบ โˆ‘i=1nni=O(nlogโกn)ใ€‚ๅ…ถไฝ™่ฝฌ็งปไธบ O(n)๏ผŒๆ•…ๆ€ปๅคๆ‚ๅบฆไธบ O(nlogโกn)ใ€‚

่€ƒ่™‘ๅฎž็Žฐ๏ผŒๅœจๆฏๆฌก่ฎก็ฎ—ๅ‡บ fi ็š„ๆ—ถๅ€™๏ผŒๅฐ†ๆ‰€ๆœ‰็š„ fki ้ƒฝๅŠ ไธŠ fiโˆ’fiโˆ’1๏ผŒ่ฟ™ๆ ท็ฉบ้—ดๅคๆ‚ๅบฆๅฐฑๆ˜ฏ O(n)ใ€‚

cpp
const int maxn = 4000005;

int n, mod;

void add(int& x, int y) {
    x += y;
    if (x >= mod) {
        x -= mod;
    } else if (x < 0) {
        x += mod;
    }
}

int f[maxn];

int main() {
    read(n), read(mod);
    f[1] = 1;
    for (int i = 2; i <= n; ++i) {
        int tmp = f[i - 1] << 1 | 1;
        if (tmp >= mod) {
            tmp -= mod;
        }
        add(f[i], tmp);
        if (i == 2) {
            f[i] = 2;
        }
        for (int j = i << 1; j <= n; j += i) {
            add(f[j], f[i]);
            add(f[j], -f[i - 1]);
        }
    }
    writeln(f[n]);
    return 0;
}

Cite this post

@misc{pu2021oiicpccodeforcescf1558b,
  author = {Pu, Fanyi},
  title  = {CodeForces 1558B Up the Strip},
  year   = {2021},
  month  = {8},
  url    = {https://pufanyi.com/blog/oi-icpc/codeforces/cf1558b}
}