1.31闲话

我想看拜年祭呃呃呃呃呃呃我要听古风燃曲我不要听闭眼我触摸幻想的边界这种当然我不是说不好听但是我要听古风燃曲aaaaaaaaaaaaaa蜀黍能不能给点力aaaaaaaaaaaaaaaaaaaaaaaa我要听万古生香我要听权御天下我要听九九八十一我要听万象霜天我要听万神纪

推歌:万神纪/星尘 by 邪叫教主

挺好听的,但是我似乎没听过几首五维介质的歌,只能算是听过


快速傅里叶变换

FFT是用来求两个多项式乘积/卷积的

  • 复数

    表示为 \(a+b_i\)

  • 复平面

    复数可以在复平面里表示 \((a_i,b_i)\),这个点和原点构成一个向量,模长是这个向量的长度,复角是它的向量与 \(x\) 轴的夹角

  • 复数意义上的单位根

    有一个以原点为圆心的半径为\(1\)的圆,对其平分成\(n\)等分

    \(\omega_n^k\) 表示 \(\frac{2\pi}{n}k\),称作 \(n\) 次单位根

    • 性质

      \(①\). \(\omega_n^i \ne \omega_n^j\)

      \(②\). \(\omega_n^k = \cos \frac{2k\pi}{n}+\text i \sin \frac{2k\pi}{n}\)

      \(③\). \(\omega_n^0=\omega_n^n=1\)

      \(④\). \(\omega_{2n}^{2k}=\omega_{n}^k\)

      \(⑤\). \(\omega_{n}^{k+\frac{n}{2}}=-\omega_{n}^{k}\)

  • 什么叫多项式乘积?

    就是卷积

    设两个多项式 \(A(x)=a_0+a_1x+a_2x^2\cdots\)\(B(x)=b_0+b_1x+b_2x^2\cdots\)

    其卷积就是两个多项式相乘(\(A(x)B(x)\))

    我们发现直接做再合并同类项就是\(n^2\)的时间复杂度

    快速傅里叶变换可以在\(O(n \log n)\)的复杂度求出两个多项式卷积的值

  • 多项式的性质

    一个\(n\)次多项式,我们可以用\(n+1\)个不同点唯一确定这个多项式

    这意味着我们可以用\(n+1\)个点来表示多项式,这被称作点表示法

    • 点表示法有什么好处

      如果我们要求\(A(x)\)\(B(x)\)的乘积\(C(x)\)

      我们可以用点表示法去求乘积

      如果我们要求\(C(x_1)\),我们发现\(C(x_1)=A(x_1)B(x_1)\)

      那么求出来\(C\)所用的复杂度为\(O(n)\)

  • 系数表示法转化成点表示法

    我们只要把系数表示法快速转化成点表示法,并且还能把点表示法快速转化成系数表示法就可以快速计算了

    这一步FFT的复杂度为\(O(n \log n)\)

    我们需要让奇偶次数分开

    \[\begin{align} A(x) &=a_0+a_1x+\cdots+a_{n-1}x^{n-1}\\ &=(a_0+a_2x^2+\cdots+a_{n-2}x^{n-2})+(a_1x+a_3x^3+\cdots+a_{n-1}x^{n-1}) \end{align} \]

    我们让\(A_1(x)=(a_0+a_2x+a_4x^2+\cdots+a_{n-2}x^{\frac{n}{2}-1})\)

    \(A_2(x)=(a_1+a_3x+a_5x^2+\cdots+a_{n-1}x^{\frac{n}{2}-1})\)

    那么

    \[A(x)=A_1(x^2)+xA_2(x^2) \]

    \(\omega_{n}^{k}\)带入,大力分讨

    • \(k \in [0,\frac{n}{2}-1)\)

      带入得到

      \[\begin{align} A(\omega_n^k) &=A_1(\omega_n^{2k})+\omega_{n}^{k}A_2(\omega_n^{2k})\\ &=A_1(\omega_{\frac{n}{2}}^k)+\omega_{n}^{k}A_2(\omega_{\frac{n}{2}}^{k}) \end{align}\]

    • \(k \in [\frac{n}{2},n-1)\)

      带入得到

      \[\begin{align} A(\omega_n^{k+\frac{n}{2}}) &=A_1(\omega_n^{2k})+\omega_{n}^{k+\frac{n}{2}}A_2(\omega_n^{2k})\\ &=A_1(\omega_{\frac{n}{2}}^k)-\omega_{n}^{k}A_2(\omega_{\frac{n}{2}}^{k}) \end{align}\]

    那么求出\(A(w_n^{k}) k\in (0,n]\)区间的所有值就可以处理了

    因为\(A(w_n^{k})=A_1(w_{\frac{n}{2}}^k)A_2(w_{\frac{n}{2}}^k)\)

    只需要递归求\(\frac{n}{2}\)的两个区间即可

    最多会递归\(\log n\)层,每层都是\(O(n)\)

    所以复杂度是\(O(n \log n)\)

  • 点表示法求出系数表达式

    FFT的逆变换怎么搞?

    已有\(n\)个点\((\omega_n^{k},A(\omega_n^{k}))\)

    我们为了方便将其称之为\((x_k,y_k)\)

    \[C_k=\sum_{i=1}^{n-1}y_i(\omega_n^{-k})^i \]

    我们可以把这个当做一个关于\(y\)的多项式,\(B(x)=y_0+y_1x+\cdots+y_{n-1}x^{n-1}\)

    \[C_k=B(\omega_{n}^{-k}) \]

    我们可以再做一次傅里叶变换来求解系数表示式

    但是\(C_k\)并不是原多项式的系数,需要再除以一个\(n\)

    \[\begin{align} C_k=\sum_{i=1}^{n-1}y_i(\omega_n^{-k})^i &=\sum_{i=1}^{n-1}(\sum_{j=0}^{n-1}a_j{\omega_n^{i}}^j){\omega_n^{-k}}^i\\ &=\sum_{i=0}^{n-1}(\sum_{j=0}^{n-1}a_j(\omega_{n}^{j-k}))^i\\ &=\sum_{j=0}^{n-1}a_j(\sum_{i=0}^{n-1}(\omega_{n}^{j-k})^{i}) \end{align}\]

    我们把\(\sum_{i=0}^{n-1}(\omega_{n}^{j-k})^{i}\)可以看做一个多项式

    \(S(x)=1+x+x^2\cdots+x^{n-1}\)

    这么这里就相当于\(S(\omega_{n}^{k})\)

    分两种情况来看

    • \(①.\) \(k \ne 0\)

      \[S(\omega_{n}^{k}) \gets \omega_{n}^{k}S(\omega_{n}^{k}) \]

      发现这两个式相等

      所以\((1-\omega_{n}^{k})S(\omega_{n}^{k})=0\)

      因为\(\omega_{n}^{k}\ne 1\)

      所以\(S(\omega_{n}^{k})=0\)

    • \(②.\) \(k=0\)

      \(S(\omega_{n}^k)=S(1)=n\)

    因此

    \[\sum_{j=0}^{n-1}a_j(\sum_{i=0}^{n-1}(\omega_{n}^{j-k})^{i})=na_k \]

  • 实现

    因为递归实现的 FFT 常数巨大,所以我们要用迭代实现

    我们对于要计算的去分为奇数项和偶数项

    分成后的多项式发现可以再分

    分到最后,我们发现,每一位对应的系数的二进制表示是这个位置原本系数对应二进制翻转过来

    比如\(a_1(001)\)\(a_4(100)\)

    还有\(a_1(0001)\)\(a_7(1000)\)

  • 代码

    const double PI=acos(-1);
    struct Complex{
    	double x,y;
    	Complex operator+(const Complex&t)const{
    		return {x+t.x , y+t.y};
    	} 
    	Complex operator-(const Complex&t)const{
    		return {x-t.x,y-t.y};
    	}
    	Complex operator*(const Complex&t)const{
    		return {x*t.x-y*t.y,x*t.y+y*t.x};
    	}
    }a[N],b[N];
    int rev[N],bit,tot;
    int n,m;
    void fft(Complex a[],int inv){
    	for(int i=0;i<tot;i++)
    		if(i<rev[i])
    			swap(a[i],a[rev[i]]);
    	for(int mid=1;mid<tot;mid<<=1){
    		auto w1=Complex({cos(PI/mid),inv*sin(PI/mid)});
    		for(int i=0;i<tot;i+=mid*2){
    			auto wk=Complex({1,0});
    			for(int j=0;j<mid;j++,wk=wk*w1){
    				auto x=a[i+j],y=wk*a[i+j+mid];
    				a[i+j]=x+y,a[i+j+mid]=x-y;
    			}
    		}
    	}
    }
    signed main(){
    	// fire();
    	cin(n,m);
    	for(int i=0;i<=n;i++) cin(a[i].x);
    	for(int i=0;i<=m;i++) cin(b[i].x);
    	while((1<<bit)<n+m+1) bit++;
    	tot=1<<bit;
    	for(int i=0;i<tot;i++)
    		rev[i]=(rev[i>>1]>>1)|((i&1)<<(bit-1));
    	fft(a,1),fft(b,1);
    	for(int i=0;i<tot;i++)
    		a[i]=a[i]*b[i];
    	fft(a,-1);
    	for(int i=0;i<=n+m;i++)
    		cout((int)(a[i].x/tot+0.5)," ");
    }
    

多项式乘法完整代码

点击查看代码
#include<bits/stdc++.h>
inline void fire(){freopen("data.in","r",stdin);freopen("data.out","w",stdout);}
namespace Fast_I {char *_Buf, *_Start_ptr, *_End_ptr;std::streambuf* inbuf;unsigned int Size;bool _Ok;struct Fast_Istream {operator bool(){return _Ok; }Fast_Istream(std::streambuf*, unsigned int);Fast_Istream(unsigned int);Fast_Istream(const char*, unsigned int);Fast_Istream& operator>>(char&);Fast_Istream& operator>>(char*);Fast_Istream& operator>>(bool&);Fast_Istream& operator>>(short&);Fast_Istream& operator>>(int&);Fast_Istream& operator>>(long&);Fast_Istream& operator>>(long long&);Fast_Istream& operator>>(unsigned short&);Fast_Istream& operator>>(unsigned int&);Fast_Istream& operator>>(unsigned long&);Fast_Istream& operator>>(unsigned long long&);Fast_Istream& operator>>(float&);Fast_Istream& operator>>(double&);Fast_Istream& operator>>(long double&);Fast_Istream& operator>>(std::string&);template <typename Typex>void operator()(Typex& _Val) { *this >> _Val; }template <typename Typex, typename... More>void operator()(Typex&, More&...);std::streambuf* rdbuf() { return inbuf; }void rdbuf(std::streambuf* _inbuf) { inbuf = _inbuf; }void rdbuf(const char*);void pop();char peek();};}
namespace Fast_O {std::string buf;std::streambuf* outbuf;struct Fast_Ostream {Fast_Ostream(std::streambuf*, unsigned int);Fast_Ostream(std::streambuf* out) { outbuf = out; }Fast_Ostream(const char*, unsigned int);Fast_Ostream(unsigned int);void flush();~Fast_Ostream();void endl() { buf.push_back('\n'); }template <typename Typex>void endl(const Typex& _Val);template <typename Typex, typename... More>void endl(const Typex&, const More&...);template <typename Typex>void operator()(const Typex& _Val);template <typename Typex, typename... More>void operator()(const Typex&, const More&...);Fast_Ostream& operator<<(char);Fast_Ostream& operator<<(const char*);Fast_Ostream& operator<<(const std::string&);Fast_Ostream& operator<<(bool);Fast_Ostream& operator<<(short);Fast_Ostream& operator<<(int);Fast_Ostream& operator<<(long);Fast_Ostream& operator<<(long long);Fast_Ostream& operator<<(unsigned short);Fast_Ostream& operator<<(unsigned int);Fast_Ostream& operator<<(unsigned long);Fast_Ostream& operator<<(unsigned long long);std::streambuf* rdbuf() { return outbuf; }void rdbuf(std::streambuf* _outbuf) { outbuf = _outbuf; }void rdbuf(const char*);};}
namespace Fast_IO {Fast_I::Fast_Istream fin(std::cin.rdbuf(), 1048576);Fast_O::Fast_Ostream fout(std::cout.rdbuf()); }
#define cin Fast_IO::fin
#define cout Fast_IO::fout
namespace Fast_I {Fast_Istream::Fast_Istream(std::streambuf* in, unsigned int Sz) {_Ok = 1;Fast_I::Size = Sz;inbuf = in;_Start_ptr = _End_ptr = _Buf = new char[Sz];}Fast_Istream::Fast_Istream(const char* in, unsigned int Sz) {_Ok = 1;Fast_I::Size = Sz;rdbuf(in);_Start_ptr = _End_ptr = _Buf = new char[Sz];}Fast_Istream::Fast_Istream(unsigned int Sz) {_Ok = 1;Fast_I::Size = Sz;_Start_ptr = _End_ptr = _Buf = new char[Sz];}void Fast_Istream::rdbuf(const char* File) {static std::ifstream __In__(File);rdbuf(__In__.rdbuf());}void Get_Char(char& _Val) {if (_Start_ptr == _End_ptr) {_Start_ptr = _Buf;_End_ptr = _Buf + inbuf->sgetn(_Buf, Size);}if (_Start_ptr == _End_ptr) {_Val = -1;_Ok = 0;} else {_Val = *_Start_ptr++;}}Fast_Istream& Fast_Istream::operator>>(char& _Val) {if(_Ok){Get_Char(_Val);while (_Val == 32 || _Val == 10 || _Val == 13 || _Val == 8 || _Val == 9 || _Val == 7 || _Val == 12 || _Val == 11) {Get_Char(_Val);}}return *this;}Fast_Istream& Fast_Istream::operator>>(char* _Val) {if (_Ok) {Get_Char(*_Val);while (*_Val == 32 || *_Val == 10 || *_Val == 13 || *_Val == 8 ||*_Val == 9 || *_Val == 7 || *_Val == 12 || *_Val == 11) {Get_Char(*_Val);}while (*_Val != 32 && *_Val != 10 && *_Val && *_Val != -1 && *_Val != 9 &&*_Val != 11 && *_Val != 12) {Get_Char(*++_Val);}*_Val = 0;--_Start_ptr;}return *this;}Fast_Istream& Fast_Istream::operator>>(std::string& _Val) {if (_Ok) {char c;Get_Char(c);while (c == 32 || c == 10 || c == 13 || c == 8 || c == 9 || c == 7 ||c == 12 || c == 11) {Get_Char(c);}for (_Val.clear();c != 32 && c != 10 && c && c != -1 && c != 9 && c != 11 && c != 12;Get_Char(c)) {_Val.push_back(c);}--_Start_ptr;}return *this;}template <typename Typex>void Get_Int(Typex& _Val) {if (_Ok) {char ch;bool _F = 0;for (Get_Char(ch); (ch < 48 || ch > 57) && ch != -1; Get_Char(ch)) {_F = ch == 45;}for (_Val = 0; ch > 47 && ch < 58 && ch != -1; Get_Char(ch)) {_Val = _Val * 10 + (ch ^ 48);}if (_F) {_Val = ~_Val + 1;}--_Start_ptr;}}template <typename Typex>void Get_Unsigned(Typex& _Val) {if (_Ok) {char ch;Get_Char(ch);while ((ch < 48 || ch > 57) && ch != -1) {Get_Char(ch);}for (_Val = 0; ch > 47 && ch < 58 && ch != -1; Get_Char(ch)) {_Val = _Val * 10 + (ch ^ 48);}--_Start_ptr;}}template <typename Typex>void Get_Double(Typex& _Val) {if(_Ok){char ch;bool _F = 0;for (Get_Char(ch); (ch < 48 || ch > 57) && ch != -1; Get_Char(ch)) {_F = ch == 45;}for (_Val = 0; ch > 47 && ch < 58 && ch != -1; Get_Char(ch)) {_Val = _Val * 10 + (ch ^ 48);}if (ch == 46) {unsigned long long _Pow = 1;for (Get_Char(ch); ch > 47 && ch < 58 && ch != -1; Get_Char(ch)) {_Val += Typex((ch ^ 48) * 1.0 / (_Pow *= 10));}}if (_F) {_Val = -_Val;}--_Start_ptr;}}Fast_Istream& Fast_Istream::operator>>(bool& _Val) {if(_Ok){char ch;Get_Char(ch);while (ch == 32 || ch == 10 || ch == 13 || ch == 8 || ch == 9 || ch == 7 ||ch == 12 || ch == 11) {Get_Char(ch);}while (ch != 32 && ch != 10 && ch && ch != -1 && ch != 9 && ch != 11 &&ch != 12) {_Val |= ch != 48;Get_Char(ch);}--_Start_ptr;}return *this;}Fast_Istream& Fast_Istream::operator>>(short& _Val) {Get_Int(_Val);return *this;}Fast_Istream& Fast_Istream::operator>>(int& _Val) {Get_Int(_Val);return *this;}Fast_Istream& Fast_Istream::operator>>(long& _Val) {Get_Int(_Val);return *this;}Fast_Istream& Fast_Istream::operator>>(long long& _Val) {Get_Int(_Val);return *this;}Fast_Istream& Fast_Istream::operator>>(unsigned short& _Val) {Get_Unsigned(_Val);return *this;}Fast_Istream& Fast_Istream::operator>>(unsigned int& _Val) {Get_Unsigned(_Val);return *this;}Fast_Istream& Fast_Istream::operator>>(unsigned long& _Val) {Get_Unsigned(_Val);return *this;}Fast_Istream& Fast_Istream::operator>>(unsigned long long& _Val) {Get_Unsigned(_Val);return *this;}Fast_Istream& Fast_Istream::operator>>(float& _Val) {Get_Double(_Val);return *this;}Fast_Istream& Fast_Istream::operator>>(double& _Val) {Get_Double(_Val);return *this;}Fast_Istream& Fast_Istream::operator>>(long double& _Val) {Get_Double(_Val);return *this;}template <typename Typex, typename... More>void Fast_Istream::operator()(Typex& _Val, More&... _More) {*this >> _Val;operator()(_More...);}void Fast_Istream::pop() {char ch;Get_Char(ch);}char Fast_Istream::peek() {if (_Start_ptr == _End_ptr) {_Start_ptr = _Buf;_End_ptr = _Buf + inbuf->sgetn(_Buf, Size);}if (_Start_ptr == _End_ptr) {_Ok = 0;return -1;} else {return *_Start_ptr;}}}
namespace Fast_O {Fast_Ostream::Fast_Ostream(std::streambuf* out, unsigned int Size) {buf.reserve(Size);outbuf = out;}Fast_Ostream::Fast_Ostream(const char* File, unsigned int Size) {buf.reserve(Size);rdbuf(File);}void Fast_Ostream::rdbuf(const char* File) {static std::ofstream __Out__(File);rdbuf(__Out__.rdbuf());}Fast_Ostream::Fast_Ostream(unsigned int Size) {buf.reserve(Size);}void Fast_Ostream::flush() {outbuf->sputn(buf.data(), buf.size());buf.clear();}Fast_Ostream::~Fast_Ostream() {flush();}Fast_Ostream& Fast_Ostream::operator<<(char _Val) {buf.push_back(_Val);return *this;}Fast_Ostream& Fast_Ostream::operator<<(const char* _Val) {while (*_Val) {buf.push_back(*_Val++);}return *this;}Fast_Ostream& Fast_Ostream::operator<<(const std::string& _Val) {for (auto&& i : _Val) {buf.push_back(i);}return *this;}template <typename Typex>void Put_Unsigned(Typex _Val) {char* _Stack = (char*)malloc(sizeof(Typex) * 3);unsigned S_top = 0;while (_Val) {_Stack[++S_top] = (_Val % 10) ^ 48;_Val /= 10;}if (!S_top) {buf.push_back('0');}while (S_top) {buf.push_back(_Stack[S_top--]);}free(_Stack);}void Put_Int(long long _Val) {if (_Val < 0) {buf.push_back('-');Put_Unsigned(~_Val + 1);} else {Put_Unsigned(_Val);}}Fast_Ostream& Fast_Ostream::operator<<(bool _Val) {buf.push_back(_Val ? '1' : '0');return *this;}Fast_Ostream& Fast_Ostream::operator<<(short _Val) {Put_Int(_Val);return *this;}Fast_Ostream& Fast_Ostream::operator<<(int _Val) {Put_Int(_Val);return *this;}Fast_Ostream& Fast_Ostream::operator<<(long _Val) {Put_Int(_Val);return *this;}Fast_Ostream& Fast_Ostream::operator<<(long long _Val) {Put_Int(_Val);return *this;}Fast_Ostream& Fast_Ostream::operator<<(unsigned short _Val) {Put_Unsigned(_Val);return *this;}Fast_Ostream& Fast_Ostream::operator<<(unsigned int _Val) {Put_Unsigned(_Val);return *this;}Fast_Ostream& Fast_Ostream::operator<<(unsigned long _Val) {Put_Unsigned(_Val);return *this;}Fast_Ostream& Fast_Ostream::operator<<(unsigned long long _Val) {Put_Unsigned(_Val);return *this;}template <typename Typex>void Fast_Ostream::endl(const Typex& _Val) {*this << _Val << '\n';}template <typename Typex, typename... More>void Fast_Ostream::endl(const Typex& _Val, const More&... _More) {*this << _Val;endl(_More...);}template <typename Typex>void Fast_Ostream::operator()(const Typex& _Val) {*this << _Val;}template <typename Typex, typename... More>void Fast_Ostream::operator()(const Typex& _Val, const More&... _More) {*this << _Val;operator()(_More...);}}
#define ull unsigned long long
#define int long long
#define INF (0x66ccff0712ll)
#define N (0x66ccff)
#define M (0x6cf)
#define MAXN (1e6+5)
#define MAXM (1e5+5)
#define lc (q<<1)
#define rc (q<<1|1)
#define cerr std::cerr
#define sort std::stable_sort
#define re register
#define lower_bound std::lower_bound
#define upper_bound std::upper_bound
#define unique std::unique
#define string std::string
#define pair std::pair
#define vector std::vector
#define map std::map
#define set std::set
#define queue std::queue
#define make_pair std::make_pair
#define priority_queue std::priority_queue
#define bitset std::bitset
#define deque std::deque
#define array std::array
#define unordered_set std::unordered_set
#define unordered_map std::unordered_map
#define list std::list
#define it map<int,int>::iterator
#define min(a,b) (a)>(b)?(b):(a)
#define max(a,b) (a)<(b)?(b):(a)
#define PII pair<int,int>
#define swap std::swap
// #define debug
const char endl='\n';
const int mod1=998244353,mod2=1e9+7,mod3=1e9+9;
const double PI=acos(-1);
struct Complex{
    double x,y;
    Complex operator+(const Complex&t)const{
        return {x+t.x , y+t.y};
    } 
    Complex operator-(const Complex&t)const{
        return {x-t.x,y-t.y};
    }
    Complex operator*(const Complex&t)const{
        return {x*t.x-y*t.y,x*t.y+y*t.x};
    }
}a[N],b[N];
int rev[N],bit,tot;
int n,m;
void fft(Complex a[],int inv){
    for(int i=0;i<tot;i++)
        if(i<rev[i])
            swap(a[i],a[rev[i]]);
    for(int mid=1;mid<tot;mid<<=1){
        auto w1=Complex({cos(PI/mid),inv*sin(PI/mid)});
        for(int i=0;i<tot;i+=mid*2){
            auto wk=Complex({1,0});
            for(int j=0;j<mid;j++,wk=wk*w1){
                auto x=a[i+j],y=wk*a[i+j+mid];
                a[i+j]=x+y,a[i+j+mid]=x-y;
            }
        }
    }
}
signed main(){
    // fire();
    cin(n,m);
    for(int i=0;i<=n;i++) cin(a[i].x);
    for(int i=0;i<=m;i++) cin(b[i].x);
    while((1<<bit)<n+m+1) bit++;
    tot=1<<bit;
    for(int i=0;i<tot;i++)
        rev[i]=(rev[i>>1]>>1)|((i&1)<<(bit-1));
    fft(a,1),fft(b,1);
    for(int i=0;i<tot;i++)
        a[i]=a[i]*b[i];
    fft(a,-1);
    for(int i=0;i<=n+m;i++)
        cout((int)(a[i].x/tot+0.5)," ");
}

写FFT突然会写主席树那题了eeee

点击查看代码

#include<bits/stdc++.h>
inline void fire(){freopen("data.in","r",stdin);freopen("data.out","w",stdout);}
namespace Fast_I {char *_Buf, *_Start_ptr, *_End_ptr;std::streambuf* inbuf;unsigned int Size;bool _Ok;struct Fast_Istream {operator bool(){return _Ok; }Fast_Istream(std::streambuf*, unsigned int);Fast_Istream(unsigned int);Fast_Istream(const char*, unsigned int);Fast_Istream& operator>>(char&);Fast_Istream& operator>>(char*);Fast_Istream& operator>>(bool&);Fast_Istream& operator>>(short&);Fast_Istream& operator>>(int&);Fast_Istream& operator>>(long&);Fast_Istream& operator>>(long long&);Fast_Istream& operator>>(unsigned short&);Fast_Istream& operator>>(unsigned int&);Fast_Istream& operator>>(unsigned long&);Fast_Istream& operator>>(unsigned long long&);Fast_Istream& operator>>(float&);Fast_Istream& operator>>(double&);Fast_Istream& operator>>(long double&);Fast_Istream& operator>>(std::string&);template <typename Typex>void operator()(Typex& _Val) { *this >> _Val; }template <typename Typex, typename... More>void operator()(Typex&, More&...);std::streambuf* rdbuf() { return inbuf; }void rdbuf(std::streambuf* _inbuf) { inbuf = _inbuf; }void rdbuf(const char*);void pop();char peek();};}
namespace Fast_O {std::string buf;std::streambuf* outbuf;struct Fast_Ostream {Fast_Ostream(std::streambuf*, unsigned int);Fast_Ostream(std::streambuf* out) { outbuf = out; }Fast_Ostream(const char*, unsigned int);Fast_Ostream(unsigned int);void flush();~Fast_Ostream();void endl() { buf.push_back('\n'); }template <typename Typex>void endl(const Typex& _Val);template <typename Typex, typename... More>void endl(const Typex&, const More&...);template <typename Typex>void operator()(const Typex& _Val);template <typename Typex, typename... More>void operator()(const Typex&, const More&...);Fast_Ostream& operator<<(char);Fast_Ostream& operator<<(const char*);Fast_Ostream& operator<<(const std::string&);Fast_Ostream& operator<<(bool);Fast_Ostream& operator<<(short);Fast_Ostream& operator<<(int);Fast_Ostream& operator<<(long);Fast_Ostream& operator<<(long long);Fast_Ostream& operator<<(unsigned short);Fast_Ostream& operator<<(unsigned int);Fast_Ostream& operator<<(unsigned long);Fast_Ostream& operator<<(unsigned long long);std::streambuf* rdbuf() { return outbuf; }void rdbuf(std::streambuf* _outbuf) { outbuf = _outbuf; }void rdbuf(const char*);};}
namespace Fast_IO {Fast_I::Fast_Istream fin(std::cin.rdbuf(), 1048576);Fast_O::Fast_Ostream fout(std::cout.rdbuf()); }
#define cin Fast_IO::fin
#define cout Fast_IO::fout
namespace Fast_I {Fast_Istream::Fast_Istream(std::streambuf* in, unsigned int Sz) {_Ok = 1;Fast_I::Size = Sz;inbuf = in;_Start_ptr = _End_ptr = _Buf = new char[Sz];}Fast_Istream::Fast_Istream(const char* in, unsigned int Sz) {_Ok = 1;Fast_I::Size = Sz;rdbuf(in);_Start_ptr = _End_ptr = _Buf = new char[Sz];}Fast_Istream::Fast_Istream(unsigned int Sz) {_Ok = 1;Fast_I::Size = Sz;_Start_ptr = _End_ptr = _Buf = new char[Sz];}void Fast_Istream::rdbuf(const char* File) {static std::ifstream __In__(File);rdbuf(__In__.rdbuf());}void Get_Char(char& _Val) {if (_Start_ptr == _End_ptr) {_Start_ptr = _Buf;_End_ptr = _Buf + inbuf->sgetn(_Buf, Size);}if (_Start_ptr == _End_ptr) {_Val = -1;_Ok = 0;} else {_Val = *_Start_ptr++;}}Fast_Istream& Fast_Istream::operator>>(char& _Val) {if(_Ok){Get_Char(_Val);while (_Val == 32 || _Val == 10 || _Val == 13 || _Val == 8 || _Val == 9 || _Val == 7 || _Val == 12 || _Val == 11) {Get_Char(_Val);}}return *this;}Fast_Istream& Fast_Istream::operator>>(char* _Val) {if (_Ok) {Get_Char(*_Val);while (*_Val == 32 || *_Val == 10 || *_Val == 13 || *_Val == 8 ||*_Val == 9 || *_Val == 7 || *_Val == 12 || *_Val == 11) {Get_Char(*_Val);}while (*_Val != 32 && *_Val != 10 && *_Val && *_Val != -1 && *_Val != 9 &&*_Val != 11 && *_Val != 12) {Get_Char(*++_Val);}*_Val = 0;--_Start_ptr;}return *this;}Fast_Istream& Fast_Istream::operator>>(std::string& _Val) {if (_Ok) {char c;Get_Char(c);while (c == 32 || c == 10 || c == 13 || c == 8 || c == 9 || c == 7 ||c == 12 || c == 11) {Get_Char(c);}for (_Val.clear();c != 32 && c != 10 && c && c != -1 && c != 9 && c != 11 && c != 12;Get_Char(c)) {_Val.push_back(c);}--_Start_ptr;}return *this;}template <typename Typex>void Get_Int(Typex& _Val) {if (_Ok) {char ch;bool _F = 0;for (Get_Char(ch); (ch < 48 || ch > 57) && ch != -1; Get_Char(ch)) {_F = ch == 45;}for (_Val = 0; ch > 47 && ch < 58 && ch != -1; Get_Char(ch)) {_Val = _Val * 10 + (ch ^ 48);}if (_F) {_Val = ~_Val + 1;}--_Start_ptr;}}template <typename Typex>void Get_Unsigned(Typex& _Val) {if (_Ok) {char ch;Get_Char(ch);while ((ch < 48 || ch > 57) && ch != -1) {Get_Char(ch);}for (_Val = 0; ch > 47 && ch < 58 && ch != -1; Get_Char(ch)) {_Val = _Val * 10 + (ch ^ 48);}--_Start_ptr;}}template <typename Typex>void Get_Double(Typex& _Val) {if(_Ok){char ch;bool _F = 0;for (Get_Char(ch); (ch < 48 || ch > 57) && ch != -1; Get_Char(ch)) {_F = ch == 45;}for (_Val = 0; ch > 47 && ch < 58 && ch != -1; Get_Char(ch)) {_Val = _Val * 10 + (ch ^ 48);}if (ch == 46) {unsigned long long _Pow = 1;for (Get_Char(ch); ch > 47 && ch < 58 && ch != -1; Get_Char(ch)) {_Val += Typex((ch ^ 48) * 1.0 / (_Pow *= 10));}}if (_F) {_Val = -_Val;}--_Start_ptr;}}Fast_Istream& Fast_Istream::operator>>(bool& _Val) {if(_Ok){char ch;Get_Char(ch);while (ch == 32 || ch == 10 || ch == 13 || ch == 8 || ch == 9 || ch == 7 ||ch == 12 || ch == 11) {Get_Char(ch);}while (ch != 32 && ch != 10 && ch && ch != -1 && ch != 9 && ch != 11 &&ch != 12) {_Val |= ch != 48;Get_Char(ch);}--_Start_ptr;}return *this;}Fast_Istream& Fast_Istream::operator>>(short& _Val) {Get_Int(_Val);return *this;}Fast_Istream& Fast_Istream::operator>>(int& _Val) {Get_Int(_Val);return *this;}Fast_Istream& Fast_Istream::operator>>(long& _Val) {Get_Int(_Val);return *this;}Fast_Istream& Fast_Istream::operator>>(long long& _Val) {Get_Int(_Val);return *this;}Fast_Istream& Fast_Istream::operator>>(unsigned short& _Val) {Get_Unsigned(_Val);return *this;}Fast_Istream& Fast_Istream::operator>>(unsigned int& _Val) {Get_Unsigned(_Val);return *this;}Fast_Istream& Fast_Istream::operator>>(unsigned long& _Val) {Get_Unsigned(_Val);return *this;}Fast_Istream& Fast_Istream::operator>>(unsigned long long& _Val) {Get_Unsigned(_Val);return *this;}Fast_Istream& Fast_Istream::operator>>(float& _Val) {Get_Double(_Val);return *this;}Fast_Istream& Fast_Istream::operator>>(double& _Val) {Get_Double(_Val);return *this;}Fast_Istream& Fast_Istream::operator>>(long double& _Val) {Get_Double(_Val);return *this;}template <typename Typex, typename... More>void Fast_Istream::operator()(Typex& _Val, More&... _More) {*this >> _Val;operator()(_More...);}void Fast_Istream::pop() {char ch;Get_Char(ch);}char Fast_Istream::peek() {if (_Start_ptr == _End_ptr) {_Start_ptr = _Buf;_End_ptr = _Buf + inbuf->sgetn(_Buf, Size);}if (_Start_ptr == _End_ptr) {_Ok = 0;return -1;} else {return *_Start_ptr;}}}
namespace Fast_O {Fast_Ostream::Fast_Ostream(std::streambuf* out, unsigned int Size) {buf.reserve(Size);outbuf = out;}Fast_Ostream::Fast_Ostream(const char* File, unsigned int Size) {buf.reserve(Size);rdbuf(File);}void Fast_Ostream::rdbuf(const char* File) {static std::ofstream __Out__(File);rdbuf(__Out__.rdbuf());}Fast_Ostream::Fast_Ostream(unsigned int Size) {buf.reserve(Size);}void Fast_Ostream::flush() {outbuf->sputn(buf.data(), buf.size());buf.clear();}Fast_Ostream::~Fast_Ostream() {flush();}Fast_Ostream& Fast_Ostream::operator<<(char _Val) {buf.push_back(_Val);return *this;}Fast_Ostream& Fast_Ostream::operator<<(const char* _Val) {while (*_Val) {buf.push_back(*_Val++);}return *this;}Fast_Ostream& Fast_Ostream::operator<<(const std::string& _Val) {for (auto&& i : _Val) {buf.push_back(i);}return *this;}template <typename Typex>void Put_Unsigned(Typex _Val) {char* _Stack = (char*)malloc(sizeof(Typex) * 3);unsigned S_top = 0;while (_Val) {_Stack[++S_top] = (_Val % 10) ^ 48;_Val /= 10;}if (!S_top) {buf.push_back('0');}while (S_top) {buf.push_back(_Stack[S_top--]);}free(_Stack);}void Put_Int(long long _Val) {if (_Val < 0) {buf.push_back('-');Put_Unsigned(~_Val + 1);} else {Put_Unsigned(_Val);}}Fast_Ostream& Fast_Ostream::operator<<(bool _Val) {buf.push_back(_Val ? '1' : '0');return *this;}Fast_Ostream& Fast_Ostream::operator<<(short _Val) {Put_Int(_Val);return *this;}Fast_Ostream& Fast_Ostream::operator<<(int _Val) {Put_Int(_Val);return *this;}Fast_Ostream& Fast_Ostream::operator<<(long _Val) {Put_Int(_Val);return *this;}Fast_Ostream& Fast_Ostream::operator<<(long long _Val) {Put_Int(_Val);return *this;}Fast_Ostream& Fast_Ostream::operator<<(unsigned short _Val) {Put_Unsigned(_Val);return *this;}Fast_Ostream& Fast_Ostream::operator<<(unsigned int _Val) {Put_Unsigned(_Val);return *this;}Fast_Ostream& Fast_Ostream::operator<<(unsigned long _Val) {Put_Unsigned(_Val);return *this;}Fast_Ostream& Fast_Ostream::operator<<(unsigned long long _Val) {Put_Unsigned(_Val);return *this;}template <typename Typex>void Fast_Ostream::endl(const Typex& _Val) {*this << _Val << '\n';}template <typename Typex, typename... More>void Fast_Ostream::endl(const Typex& _Val, const More&... _More) {*this << _Val;endl(_More...);}template <typename Typex>void Fast_Ostream::operator()(const Typex& _Val) {*this << _Val;}template <typename Typex, typename... More>void Fast_Ostream::operator()(const Typex& _Val, const More&... _More) {*this << _Val;operator()(_More...);}}
#define ull unsigned long long
#define ll long long
#define INF (0x66ccff0712ll)
#define N ((0x66ccff)<<2)
#define MAXN (int)(1e6+5)
#define MAXM (int)(1e5+5)
#define lc (q<<1)
#define rc (q<<1|1)
#define mid ((l+r)>>1)
#define cerr std::cerr
#define sort std::stable_sort
#define re register
#define lower_bound std::lower_bound
#define upper_bound std::upper_bound
#define unique std::unique
#define string std::string
#define pair std::pair
#define vector std::vector
#define map std::map
#define set std::set
#define queue std::queue
#define make_pair std::make_pair
#define priority_queue std::priority_queue
#define bitset std::bitset
#define deque std::deque
#define array std::array
#define unordered_set std::unordered_set
#define unordered_map std::unordered_map
#define list std::list
#define it map<int,int>::iterator
#define min(a,b) (a)>(b)?(b):(a)
#define max(a,b) (a)<(b)?(b):(a)
#define PII pair<int,int>
#define swap std::swap
#define int long long
// #define debug
const char endl='\n';
const ll mod1=998244353,mod2=1e9+7,mod3=1e9+9;
ll n,m,cnt;
ll a[N],Start[N],lasT[N],rt[N],sum[N],ls[N],rs[N];
inline void update(ll &now,ll l,ll r,ll x){
    ++cnt;
    sum[cnt]=sum[now]+1;
    ls[cnt]=ls[now];
    rs[cnt]=rs[now];
    now=cnt;
    if(l==r) return;
    if(x<=mid) update(ls[now],l,mid,x);
    else update(rs[now],mid+1,r,x);
}
inline ll query(ll x,ll y,ll l,ll r,ll k){
    if(l==r) return sum[y]-sum[x];
    if(k<=mid) return query(ls[x],ls[y],l,mid,k);
    else return query(rs[x],rs[y],mid+1,r,k)+sum[ls[y]]-sum[ls[x]];
}
signed main(){
    // fire();
    cin(n,m);
    for(int i=1;i<=n;i++){
        cin(a[i]);
        lasT[i]=Start[a[i]];
        Start[a[i]]=i;
    }
    for(int i=1;i<=n;i++){
        rt[i]=rt[i-1];
        update(rt[i],0,n,lasT[i]);
    }
    int ans=0;
    for(int i=1;i<=m;i++){
        int x,y;
        cin(x,y);
        x=(x+ans)%n+1;
        y=(y+ans)%n+1;
        if(x>y) swap(x,y); 
        ans=query(rt[x-1],rt[y],0,n,x-1);
        cout(ans,"\n");
    }
}

没存星尘的图,放个别的先用着,K8看到了别D我,不过K8不在所以估计看不到

posted @ 2024-01-31 19:04  Vsinger_洛天依  阅读(24)  评论(0编辑  收藏  举报