Submission #42048626
Source Code Expand
#include <bits/stdc++.h>
#include <atcoder/modint>
#include <atcoder/convolution>
const int MOD=998244353;
using mint = atcoder::static_modint<MOD>;
namespace CMM{
template<class T,int MOD> // T should be modint
class InvFacBinom{
std::vector<T> _inv;
int _n;
public:
std::vector<T> fac;
std::vector<T> ifac; // invfac
InvFacBinom(int n):_n(n){
fac = std::vector<T> (n+1,1);
_inv = std::vector<T> (n+1,1);
ifac = std::vector<T> (n+1,1);
for(int i=1;i<=n;i++) fac[i] = fac[i-1] * i;
for(int i=2;i<=n;i++) _inv[i] = (MOD-MOD/i) * _inv[MOD%i];
for(int i=1;i<=n;i++) ifac[i] = ifac[i-1] * _inv[i];
}
T inv(int v)const{
assert(v > 0 && v <= _n && v < MOD);
return _inv[v];
}
T binom(int n,int m)const{ return (m>n||m<0)?0:fac[n] * ifac[m] * ifac[n-m]; }
};
}
namespace CMM{
template<class T>
class Poly{
std::vector<T>_d;
public:
Poly(const std::vector<T> &d={}):_d(d){};
friend Poly operator+(const Poly&p0,const Poly&p1){
std::vector<T>r=p0._d;
if(p1._d.size()>r.size())r.resize(p1._d.size());
for(int i=0;i<(int)p1._d.size();i++)r[i]+=p1._d[i];
return r;
}
friend Poly operator-(const Poly&p0,const Poly&p1){
std::vector<T>r=p0._d;
if(p1._d.size()>r.size())r.resize(p1._d.size());
for(int i=0;i<(int)p1._d.size();i++)r[i]-=p1._d[i];
return r;
}
friend Poly operator*(const Poly&p0,const Poly&p1){ // ntt
return atcoder::convolution(p0._d,p1._d);
}
std::vector<T> coef()const{
return _d;
}
void Print() const{
for(auto v:_d) printf("%d ",v.val());
printf("\n");
}
template<int MOD>
static Poly PolyEX(const InvFacBinom<T,MOD>&ifb,int n){ // e^x
std::vector<T> p(n+1,0);
for(int i=0;i<=n;i++)p[i]=ifb.ifac[i];
return p;
}
template<int MOD>
static Poly PolyENegX(const InvFacBinom<T,MOD>&ifb,int n){ // e^{-x}
std::vector<T> p(n+1,0);
for(int i=0;i<=n;i++)p[i]=ifb.ifac[i]*(i%2?-1:1);
return p;
}
Poly Rev(int n) const{ // 颠倒[0..n]次的系数
std::vector<T>r=_d;
if(n+1>(int)r.size())r.resize(n+1);
for(int i=0;i<(int)r.size()/2;i++)std::swap(r[i],r[r.size()-1-i]);
return r;
}
Poly Modn(int n) const{ // return (this) mod x^n
std::vector<T>r=_d;
if((int)r.size()>n) r.resize(n);
return r;
}
Poly Inv(int n) const{ // return this^{-1}, s.t. this this^{-1} \equiv 1 \pmod{x^n}
assert(_d[0] != 0);
Poly r = std::vector<T>{_d[0].inv()};
for(int pwr=1;pwr<n;pwr*=2){
r = r.Modn(pwr);
r = r * (Poly({2}) - r * _d);
}
return r.Modn(n);
}
Poly Norm() const{ // 清除高位0
std::vector<T>r=_d;
while(r.size() > 1 && r.back()==0)r.pop_back();
return r;
}
std::pair<Poly,Poly> Div(const Poly<T>& B) const{ // return {A / B,A % B}
const Poly& A=*this;
int m=B._d.size()-1;
int n=std::max(A._d.size()-1,B._d.size()-1); // n >= m
// A=BC+D
auto C=(A.Rev(n)*(B.Rev(m)).Inv(n-m+1)).Modn(n-m+1).Rev(n-m);
auto D=(A-B*C).Norm();
return {C,D};
}
std::vector<T> MPE(const std::vector<T>& a) const{ // Multipoint evaluation
int sz=a.size();
std::vector<std::vector<Poly > > tree = {{}};
for(auto v:a)tree[0].push_back(std::vector<T>{-v,1}); // x-ai
while((tree[0].size() & (tree[0].size()-1)))tree[0].push_back(std::vector<T>{1}); // 1
while(tree.back().size() > 1){
std::vector<Poly >row={};
const auto&b=tree.back();
for(int i=0;i<(int)b.size()/2;i++) row.push_back(b[i*2]*b[i*2+1]);
tree.push_back(row);
}
std::vector<Poly > h = {Poly(_d)};
// h[0] 表示 h, 从上向下取mod
for(int i=tree.size()-1;i>=0;i--){
std::vector<Poly > nexth = {};
for(int j=0;j<(int)tree[i].size();j++) nexth.push_back(h[j/2].Div(tree[i][j]).second);
h = nexth;
}
std::vector<T> res;
for(int i=0;i<sz;i++) res.push_back(h[i]._d[0]);
return res;
}
};
};
using namespace CMM;
// --------------- template ------------------
typedef long long ll;
#define rep(i,a,n) for (ll i=a;i<(ll)(n);i++)
ll read(){ll r;scanf("%lld",&r);return r;}
int main(){
using namespace std;
using mint=atcoder::modint998244353;
const int MOD=998244353;
using poly=CMM::Poly<mint>;
int n=read();
InvFacBinom<mint,MOD> ifb(n+1);
vector<mint> g(n + 1); // g(x,y=1) = (-1)^j x^{ij}
vector<mint> dg(n + 1); // d g(x,y)/dy (y=1) = (-1)^j j x^{ij}
rep(i,1,n+1) rep(j,1,n/i+1){
dg[i * j] = dg[i * j] + ((j & 1) ? 1 : -1) * j;
g[i * j] = g[i * j] + ((j & 1) ? 1 : -1);
}
g[0] -= 1; // g-1
poly h = poly{dg} * (poly{g} * poly{g}).Inv(n); // dg/(g-1)^2
printf("%d\n",h.coef()[n].val());
return 0;
}
Submission Info
| Submission Time |
|
| Task |
Ex - Diff Adjacent |
| User |
cromarmot |
| Language |
C++ (GCC 9.2.1) |
| Score |
600 |
| Code Size |
5088 Byte |
| Status |
AC |
| Exec Time |
985 ms |
| Memory |
29248 KiB |
Compile Error
./Main.cpp: In function ‘ll read()’:
./Main.cpp:134:21: warning: ignoring return value of ‘int scanf(const char*, ...)’, declared with attribute warn_unused_result [-Wunused-result]
134 | ll read(){ll r;scanf("%lld",&r);return r;}
| ~~~~~^~~~~~~~~~~
Judge Result
| Set Name |
Sample |
All |
| Score / Max Score |
0 / 0 |
600 / 600 |
| Status |
|
|
| Set Name |
Test Cases |
| Sample |
example_00.txt, example_01.txt, example_02.txt |
| All |
example_00.txt, example_01.txt, example_02.txt, test_00.txt, test_01.txt, test_02.txt, test_03.txt, test_04.txt, test_05.txt, test_06.txt, test_07.txt, test_08.txt, test_09.txt, test_10.txt, test_11.txt, test_12.txt |
| Case Name |
Status |
Exec Time |
Memory |
| example_00.txt |
AC |
8 ms |
3664 KiB |
| example_01.txt |
AC |
4 ms |
3828 KiB |
| example_02.txt |
AC |
527 ms |
17844 KiB |
| test_00.txt |
AC |
885 ms |
26724 KiB |
| test_01.txt |
AC |
915 ms |
28620 KiB |
| test_02.txt |
AC |
855 ms |
24696 KiB |
| test_03.txt |
AC |
868 ms |
25728 KiB |
| test_04.txt |
AC |
243 ms |
10644 KiB |
| test_05.txt |
AC |
903 ms |
28200 KiB |
| test_06.txt |
AC |
259 ms |
10796 KiB |
| test_07.txt |
AC |
408 ms |
15592 KiB |
| test_08.txt |
AC |
189 ms |
9328 KiB |
| test_09.txt |
AC |
864 ms |
25356 KiB |
| test_10.txt |
AC |
3 ms |
3612 KiB |
| test_11.txt |
AC |
3 ms |
3640 KiB |
| test_12.txt |
AC |
985 ms |
29248 KiB |