#define _USE_MATH_DEFINES #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; class FFT { private: vector > v; void execute(const vector >& input, bool isInverse, vector >& output) const { int n = input.size(); vector > x(input.begin(), input.end()); for(int h=1; h > y = x; for(int k=0; k omega = polar(1, (isInverse? -1:1) * M_PI * k / h); for(int j=0; j y0 = y[2*w*k+j]; complex y1 = y[2*w*k+j+w] * omega; x[w*k+j] = y0 + y1; x[w*(k+h)+j] = y0 - y1; } } } output.swap(x); } public: void dft(const vector& input) { if(input.size() == 0){ v.clear(); return; } int n = 1; while(n < (int)input.size()) n *= 2; vector > x(n, 0); for(unsigned i=0; i((double)input[i], 0.0); execute(x, false, v); } void idft(vector& output) const { int n = v.size(); vector > y; execute(v, true, y); output.resize(n); for(int i=0; i a; bool sign; void normalize(){ while(!a.empty() && a.back() == 0) a.pop_back(); if(a.empty()) sign = true; } Bigint(const vector& x){ a = x; sign = true; normalize(); } public: Bigint(){ sign = true; } Bigint(long long x){ sign = (x >= 0); x = abs(x); while(x > 0){ a.push_back(x % MAX); x /= MAX; } } Bigint(const string& s){ sign = true; long long tmp = MAX; for(int i=s.size()-1; i>=0; --i){ if(tmp == MAX){ a.push_back(0); tmp = 1; } if('0' <= s[i] && s[i] <= '9'){ a.back() += (s[i] - '0') * tmp; tmp *= 10; } else if(i == 0 && s[0] == '-'){ sign = false; } else{ throw(exception()); } } normalize(); } long long getNum() const{ long long ans = 0; for(int i=a.size()-1; i>=0; --i){ ans *= MAX; ans += a[i]; } return ans * (sign? 1:-1); } string getStr() const{ ostringstream oss; if(a.size() == 0) return "0"; if(!sign) oss << '-'; for(int i=a.size()-1; i>=0; --i){ oss << a[i]; oss << setw(LEN) << setfill('0'); } return oss.str(); } Bigint operator+(const Bigint& x) const{ if(sign ^ x.sign){ Bigint tmp = x; tmp.sign = !tmp.sign; return *this - tmp; } Bigint ans; ans.sign = sign; long long carry = 0; unsigned i = 0; while(i < a.size() || i < x.a.size() || carry > 0){ if(i < a.size()) carry += a[i]; if(i < x.a.size()) carry += x.a[i]; ans.a.push_back(carry % MAX); carry /= MAX; ++ i; } return ans; } Bigint operator-(const Bigint& x) const{ if(sign ^ x.sign){ Bigint tmp = x; tmp.sign = !tmp.sign; return *this + tmp; } Bigint ans; long long carry = 0; unsigned i=0; while(i < a.size() || i < x.a.size()){ if(i < a.size()) carry += a[i]; if(i < x.a.size()) carry -= x.a[i]; if(carry < 0){ ans.a.push_back(MAX + carry); carry = -1; } else{ ans.a.push_back(carry); carry = 0; } ++ i; } if(carry == -1){ ans.sign = !ans.sign; for(unsigned j=0; j b = a; vector c = x.a; int n = max(b.size(), c.size()); b.resize(n * 2, 0); c.resize(n * 2, 0); FFT p, q, r; p.dft(b); q.dft(c); r = p * q; Bigint ans; ans.sign = !(sign ^ x.sign); r.idft(ans.a); for(int i=0; i<2*n-1; ++i){ ans.a[i+1] += ans.a[i] / MAX; ans.a[i] %= MAX; } ans.normalize(); return ans; } bool operator<(const Bigint& x) const{ if(sign ^ x.sign) return x.sign; if(a.size() != x.a.size()) return !(sign ^ (a.size() < x.a.size())); for(int i=a.size()-1; i>=0; --i){ if(a[i] != x.a[i]) return !(sign ^ (a[i] < x.a[i])); } return false; } }; // 行列の積 template vector > matrixProduct(const vector >& x, const vector >& y) { int a = x.size(); int b = x[0].size(); int c = y[0].size(); vector > z(a, vector(c, 0)); for(int i=0; i vector > matrixPower(const vector >& x, int k) { int n = x.size(); vector > y(n, vector(n, 0)); for(int i=0; i > z = x; while(k > 0){ if(k & 1) y = matrixProduct(y, z); z = matrixProduct(z, z); k >>= 1; } return y; } Bigint solve(int len) { vector > v = {{1, 1}, {1, 0}}; v = matrixPower(v, len); return v[0][1]; } int main() { int len; cin >> len; if(len == 2){ cout << 3 << endl << "INF" << endl; return 0; } Bigint ans = solve(len); if(len % 2 == 0){ Bigint x = solve(len / 2); ans = ans - x * x; } cout << len << endl << ans.getStr() << endl; return 0; }