zoukankan      html  css  js  c++  java
  • 模版

    ACM模板

     

    用于简化模运算的定理

    欧拉定理 am互质,a^phi(m)%m==1-->m为质数 a^(m-1)%m==1

    威尔逊定理 p为素数 (p-1)!%p==p-1==-1

    费马定理 p为素数,ap互质,a^(p-1)%p==1

    费马小定理 p为素数,a^p%p==a-->(a^p/a)%p==a/a-->a^(p-1)%p==1

    am不互质时若m较小可以直接找a^x%m=1,即直接for循环从1开始找x

    A^x % m = A^(x%phi(m)+phi(m)) % m (x >= phi(m))

    用于化简(a^(b^(c^...))),先算最上面的次方,然后递归回去

    换底公式 log(a)(b)=log(c)(b)/log(c)(a),当结果超过浮点数范围时用log,负数没有对数

     #pragma comment(linker, "/STACK:102400000,102400000")//手动开大栈区
    多次模规律 x=x*x%p;在一定次数后x会不再改变,即x*x%p==x

    scanf(“%[^ ]”,s);时记得初始化s[0]=0;否则输入有空行时会WA,且输入空行时返回值为0

    an次根:x=pow(a,1.0/n)

    处理误差时同时判x*x==a || (x+1)*(x+1)==a (间隔为2x+1,所以基本能处理误差)

     

    树上某个点的子树的所有信息dfs进入这个点时已经记录的信息离开这个点时已经记录的信息差集

    //multiset s.erase(2)会一次删除所有的 2,若要只删一个应用 s.erase(s.find(2))--易错

    多个样例输入 T较大且满足从小到大递推时可以将询问离线出来处理

    abs(x)在没有 using namespace std;的情况下超过 long long 会出错

    gcd计数相关:莫比乌斯反演,容斥原理,欧拉函数

    递归超过 1e5层左右就会爆栈 RE,将递归改成手写栈

     

     

     1 C(n,k+1)=C(n,k)*(n-k)/(k+1)
     2 
     3 //O(n)递推
     4 
     5 C(n,k)=n!/(k!*(n-k!))=n*(n-1)*...*(n-k+1){k个相乘}/k! (k<=n)
     6 
     7 C(n,k)=C(n,n-k)
     8 
     9 C(n,k)=C(n-1,k)+C(n-1,k-1)
    10 
    11 {杨辉等式,杨辉三角形的对称性}
    12 
    13 C(n,0)+C(n,1)+...+C(n,n-1)+C(n,n)=2^n {二项式定理}
    14 
    15 C(n,0)+C(n+1,1)+C(n+2,2)+.+C(n+r,r)=C(n+r+1,r)//把 C(n,0)看出 C(n+1,0)不断往后合并
    16 
    17 可重复组合(隔板法)
    18 
    19 从 n个元素中可重复地选 k个,n个盒子放 k个相同的球,选法为
    20 
    21 C(n+k-1,n-1)=C(n+k-1,k)
    22 
    23 有重复元素排列
    24 
    25 n个元素中有 n1个相同,n2个相同。。。
    26 
    27 n!/(n1!*n2!*...*nk!)
    28 
    29 圆排列
    30 
    31 从 n个不同元素中选 k个不分首位围成一个圆圈,方案数为
    32 
    33 A(n,k)/k 如果 k==n,则有 n!/n=(n-1)!34 
    35 条件排列
    36 
    371,2,3,4,5五个数进行排列,要求 4排在 2前面
    38 
    39 方法 1:先排 135,3!种,再插 2,4,先插 4,有四种插法,对于每种插法,2有 4,3,2,1种插法,所以种数=3!*10=60
    40 
    41 方法 2:不考虑 2,4的全排列,共有 5!种,2和 4的位置先后分布情况各半,所以种数=5!/2=60
    42 
    43 错位排列
    44 
    45 {a1,a2,...,an},ai不放在第 i个位置的种数
    46 
    47 Dn=n!*(1-1/1!+1/2!-1/3!+1/4!-...!(-1)^n/n!)
    48 
    49 f(n)=(n-1)*(f(n-1)+f(n-2)) 递推式
    组合公式
     1 一、球相同,盒子相同,且盒子不能空
     2 
     3 结论 n个相同的球放入m个相同的盒子(n≥m),不能有空盒时的放法种数等于n分解为m个数的和的种数.
     4 
     5 二、球相同,盒子相同,且盒子可以空
     6 
     7 结论 n个相同的球放入m个相同的盒子(n≥m),可以有空盒时的放法种数等于将n分解为m个、(m-1)个、
     8 
     9 (m-2)个、…、2 个、1 个数的和的所有种数之和.
    10 
    11 三、球相同,盒子不同,且盒子不能空
    12 
    13 结论 n个相同的球放入m个不同的盒子中(n≥m),不能有空盒的放法数 C(n-1,m-1).
    14 
    15 四、球相同,盒子不同,且盒子可以空
    16 
    17 结论 n个相同的球放入m个不同的盒子中(n≥m),可以有空盒的放法数 C(n+m-1,m-1).
    18 
    19 五、球不同,盒子相同,且盒子不能空
    20 
    21 .
    22 
    23 递推式:S(n,m)=S(n-1,m-1)+m*S(n-1,m)
    24 
    25 结论 n个不同的球放入m个相同的盒子中(n≥m),不能有空盒的放法种数等于n个不同的球分成m堆的种
    26 
    27 数.
    28 
    29 六、球不同,盒子相同,且盒子可以空
    30 
    31 结论 n个不同的球放入m个相同的盒子中(n≥m),可以有空盒的放法种数等于将n个不同的球分成m堆、(m
    32 
    331)堆、(m-2)堆、…、2 堆、1 堆的所有种数之和.
    34 
    35 七、球不同,盒子不同,且盒子不能空
    36 
    37 结论 n个不同的球放入m个不同的盒子中,不能有空盒的放法种数等于n个不同的球分成m堆的种数乘以m!.
    38 
    39 八、球不同,盒子不同,且盒子可以空
    40 
    41 结论 n个不同的球放入m个不同的盒子中(n≥m),可以有空盒的放法种数等于m^n种.
    球盒问题 

     n个不同的球和 m个不同球按原来顺序穿插起来,即将 n个球看成一样的,m个也是一样的,然后进行排列,

    (n+m)!/(n!m!)中插法,即将 n个球按原来顺序放入(m+1)个盒子

     1 前几项:1 1 2 5 14 42 132 429 1430 4862 16796 58786 2080127429002674440969484535357670129644790
     2 
     3 1.递归公式
     4 
     5 h(n) = h(n-1)*(4*n-2) / (n+1);
     6 
     7 2.递归公式
     8 
     9 f(n)=f(0)*f(n-1)+f(1)*f(n-2)+...+f(n-2)*f(1)+f(n-1)*f(0){累加 f(i)*f(n-i-1),i从 0到 n-1}
    10 
    11 3.组合公式 1
    12 
    13 f(n)=C(2*n,n)/(n+1)
    14 
    15 4.组合公式 2
    16 
    17 f(n)=C(2*n,n)-C(2*n,n-1)
    18 
    19 用于
    20 
    21 1 二叉数形态的计数
    22 
    23 2 火车进站后的出站顺序种数,乘法加括号的运算顺序种数
    24 
    25 3 将凸 n边形用 n-3条不相交的对角线分成 n-2个互相没有重叠的三角形的分法
    26 
    27 4
    28 
    29 n个 A和 n个 B排成一排,在任何位置 B的个数不超过 A的个数的排列种数
    Catalan(栈相关计数)
     1 假设 x为奇数,y为偶数,则 z为奇数,2z与 2x的最大公因数为 2,2z和 2x可分别写作
     2 
     3 2z = (z + x) + (z - x)
     4 
     5 2x = (z + x) - (z - x)
     6 
     7 那么跟据最大公因数性质,z + x和 z - x的最大公因数也为 2,又因为:
     8 
     9 (z + x)(z - x) = y^2,两边同除以 4得:
    10 
    11 ((z + x) / 2)((z - x) / 2) = (y / 2)^2
    12 
    13 故可令:
    14 
    15 z + x = 2m^2, z - x = 2n^2
    16 
    17 其中 z = m + n, x = m - n(m与 n互质)
    18 
    19 则有:
    20 
    21 y2 = z^2 - x^2 = (2m)^2 (2n)^2 = 4m^2 n^2
    22 
    23 即 y = 2mn。
    24 
    25 综上所述,可得到下式:
    26 
    27 x = m^2 - n^2, y = 2mn, z = m^2 + n^2. (m, n为任意自然数)
    //勾股数性质

    #ifdef ONLINE_JUDGE

    #else

    freopen("in","r",stdin);

    freopen("out","w",stdout);

    #endif

     1 struct node
     2 {
     3 int d,i;
     4 }d[110];
     5 struct cmp
     6 {
     7 bool operator ()(const node &a, const node &b)
     8 {
     9 return a.d<b.d || a.d==b.d && a.i>b.i;
    10 }
    11 };
    12 priority_queue<node, vector<node>, cmp>q;
    13 priority_queue<int, vector<int>, less<int> >q;
    14 priority_queue<int, vector<int>, greater<int> >q;
    //优先队列重载 cmp
     1 template <class T>  
     2 bool scanff(T &ret)
     3 { //Faster Input:short,int,long long,double,float
     4     char c; int sgn; T bit=0.1;  
     5     if(c=getchar(),c==EOF) return 0;  
     6     while(c!='-'&&c!='.'&&(c<'0'||c>'9')) c=getchar();  
     7     sgn=(c=='-')?-1:1;  
     8     ret=(c=='-')?0:(c-'0');  
     9     while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');  
    10     if(c==' '||c=='
    ') { ret*=sgn; return 1; }  
    11     while(c=getchar(),c>='0'&&c<='9') ret+=(c-'0')*bit,bit/=10;  
    12     ret*=sgn;  
    13     return 1;  
    14 } 
    fast input
     1 template <class T>
     2 void printff(T ret)
     3 { //Faster Output:short,int,long long
     4     char s[22];
     5     if(ret<0) { printf("-");ret=-ret; }
     6     int len=0;
     7     while(ret) { s[++len]=ret%10+'0';ret/=10; }
     8     if(!len) s[++len]='0';
     9     while(len) printf("%c",s[len--]);
    10 }
    fast output 
     1 void phi_table(int *phi,int *f,int *p,int &pn)
     2 {
     3     phi[1]=1;pn=0;
     4     int k;
     5     for(int i=2;i<N;i++)
     6     {
     7         if(!f[i]) { p[pn++]=f[i]=i;phi[i]=i-1; }
     8         for(int j=0;j<pn&&(k=p[j]*i)<N;j++)
     9         {
    10             f[k]=p[j];
    11             if(f[i]==p[j]) { phi[k]=phi[i]*p[j]; break; }
    12             else phi[k]=phi[i]*(p[j]-1);
    13         }
    14     }
    15     //for(int i=2;i<=N;i++) phi[i]+=phi[i-1];//累加
    16 }
    //欧拉函数线性筛法,phi为欧拉数组,f为素数标记数组,p为素数数组O(n) 
    1 void fa(int n,int &dn,int*d)        
    2 {
    3     dn=0;
    4     int m=sqrt(n)+0.5;
    5     for(int i=1;i<=m;i++) if(n%i==0) { d[dn++]=i;d[dn++]=n/i; }
    6     if(m*m==n) dn--;
    7     sort(d,d+dn);
    8 }
    //找n所有约数并从小到大存到d数组O(n^(1/2))
     1 void fa(int n,int &pn,int *p)
     2 {
     3     pn=0;
     4     int m=sqrt(n)+0.5;
     5     for(int i=2;i<=m;i++) if(n%i==0)
     6     {
     7         p[pn]=1;
     8         while(n%i==0)
     9         {
    10             p[pn]*=i;
    11             n/=i;
    12         }
    13         pn++;
    14     }
    15     if(n!=1) p[pn++]=n;
    16 }
    //找n所有质因子并将素数从小到大存最高幂次到d数组O(n^(1/2))
     1 void Prin()            //O(nlogn)
     2 {
     3     memset(prin,0,sizeof(prin));
     4     for(int i=2;i<N;i++) if(!prin[i])
     5         for(int j=i;j<N;j+=i)
     6         {
     7             int t=j;
     8             while(t%i==0)
     9             {
    10                 prin[j]++;
    11                 t/=i;
    12             }
    13         }
    14 }
    //筛出1到N中每个数质因子的个数,如24=2*2*2*3,则prin[24]=4,也可以改为筛质因子
     1 template<class T>
     2 T gcd(T a,T b)
     3 {
     4     while(b)
     5     {
     6         T r=b;
     7         b=a%b;
     8         a=r;
     9     }
    10     return a;
    11 }
    //非递归gcd O(logn)
     1 LL slove(LL a,LL b)
     2 {
     3     LL g = gcd(b/a,a);  
     4     while(g!=1)
     5     {
     6         a = a/g;  
     7         g = gcd(b/a, a);  
     8         }
     9     return b/a;
    10 }
    //返回最小的ans满足lcm(a,ans)=b
     1 LL quick_mod(LL t,LL n)
     2 {
     3     LL ans=1;
     4     while(n)
     5     {
     6         if(n&1) ans=ans*t%mod;
     7         t=t*t%mod;
     8         n>>=1;
     9     }
    10     return ans;
    11 }
    //t^n%mod二分快速幂O(log(n))

    //欧拉函数为 phi(n)=小于 n且与 n互质的数的个数,这些数的和为 n*phi(n)/2

    证明 共有 m 个与 n 互质的数, m  n 的欧拉函数, m=φ(n)

     ans=∑i=0,m−1 ai…(1) ,gcd(ai,n)=1&& ai<n;

    可知 gcd(ai,n−ai)=1;

     ans=∑i=0,m−1 (n−ai)…(2) , gcd(ai,n−ai)=1 && n−ai<n;

    (1) + (2)  2∗ans=n∗m,  ans=n∗φ(n)/2;

    欧拉函数引理

    1.p为素数 phi(p)=p-1

    2.p为素数 phi(p^a)=(p-1)*p^(a-1)=p^a*(1-1/p)

    3.a,b互质 phi(a*b)=phi(a)*phi(b)

    n=p1^a1*p2^a2*...*pk^ak

    phi(n)=p1^a1*(1-1/p1)*p2^a2*(1-1/p2)*...*pk^ak*(1-1/pk)=n*(1-1/p1)*(1-1/p2)*...*(1-1/pk)

     1 int euler(int n)
     2 {
     3     int ans = n;
     4     for (int i = 2; i * i <= n; i++)
     5         if (n % i == 0)
     6         {
     7             ans = ans / i * (i - 1);
     8             while (n % i == 0)
     9                 n /= i;
    10         }
    11     if (n > 1)
    12         ans = ans / n * (n - 1);
    13     return ans;
    14 }
    //O(sqrt(n))求单个数的欧拉函数,phi[n]=n/pi*(pi-1)
     1 void phi_table(int *phi, int *f, int *p, int &pn)
     2 {
     3     phi[1] = 1;
     4     pn = 0;
     5     int k;
     6     for (int i = 2; i < N; i++)
     7     {
     8         if (!f[i])
     9         {
    10             p[pn++] = f[i] = i;
    11             phi[i] = i - 1;
    12         }
    13         for (int j = 0; j < pn && (k = p[j] * i) < N; j++)
    14         {
    15             f[k] = p[j];
    16             if (f[i] == p[j])
    17             {
    18                 phi[k] = phi[i] * p[j];
    19                 break;
    20             }
    21             else
    22                 phi[k] = phi[i] * (p[j] - 1);
    23         }
    24     }
    25     //for(int i=2;i<=N;i++) phi[i]+=phi[i-1];//累加
    26 }
    //欧拉函数线性筛法,phi为欧拉数组,f为素数标记数组,p为素数数组 O(n)
     1 void prime(int &pn, int *p, bool *vis)
     2 {
     3     pn = 0;
     4     for (int i = 2; i < N; i++)
     5     {
     6         if (!vis[i])
     7             p[pn++] = i;
     8         for (int j = 0; j < pn && i * p[j] < N; j++)
     9         {
    10             vis[i * p[j]] = 1;
    11             if (i % p[j] == 0)
    12                 break;
    13         }
    14     }
    15 }
    //素数线性筛法,p为素数数组,vis为素数标记数组 O(n)
     1 int vis[N / 31], pn, p[N / 10];
     2 inline bool judge(int x) { return vis[x >> 5] & (1 << (x & 31)); }
     3 inline void setbit(int x) { vis[x >> 5] |= 1 << (x & 31); }
     4 void init()
     5 {
     6     pn = 0;
     7     memset(vis, 0, sizeof(vis));
     8     for (int i = 2; i < M; i++)
     9     {
    10         if (!judge(i))
    11             p[pn++] = i;
    12         for (int j = 0; p[j] * i < M; j++)
    13         {
    14             setbit(i * p[j]);
    15             if (i % p[j] == 0)
    16                 break;
    17         }
    18     }
    19 }
    //位压素数筛,省内存
     1 int prime(int a, int b)
     2 {
     3     memset(vis, 1, sizeof(vis));
     4     for (int i = 0; i < pn && (LL)p[i] * p[i] <= b; i++)
     5     {
     6         int x = a / p[i] + (a % p[i] != 0);
     7         if (x == 1)
     8             x++;
     9         for (LL j = (LL)x * p[i]; j <= b; j += p[i])
    10             vis[j - a] = 0; //,printf("%d
    ",j);
    11     }
    12     int ans = 0;
    13     for (LL i = 0; i + a <= b; i++)
    14         ans += vis[i];
    15     if (a == 1)
    16         ans--;
    17     return ans;
    18 }
    //区间素数筛
     1 LL cal(LL p, LL n)
     2 {
     3     p %= mod;
     4     if (p == 1)
     5         return (n + 1) % mod;
     6     LL inv = quick_mod(p - 1, mod - 2);
     7     LL t = quick_mod(p, n);
     8     if (t * p % mod != 1)
     9         return (t * p % mod - 1) * inv % mod;
    10     return (t - 1) * inv % mod * t % mod;
    11 }
    //所有约数的和=(p[i]^(e[i]+1) - 1)/(p[i]-1) ,0<=i<pn,累乘 //计算(p^0+p^1+...+p^n)%mod,p==1时和 p^(n+1)%mod==1时会出错
     1 int log_mod(int a, int b)
     2 {
     3     int m, v, e = 1;
     4     m = (int)sqrt(mod + 0.5);
     5     v = Inv(quick_mod(a, m));
     6     map<int, int> x;
     7     x[1] = 0;
     8     for (int i = 1; i < m; i++)
     9     {
    10         e = (LL)e * a % mod;
    11         if (!x.count(e))
    12             x[e] = i;
    13     }
    14 
    15     for (int i = 0; i < m; i++)
    16     {
    17         if (x.count(b))
    18             return i * m + x[b];
    19         b = (LL)b * v % mod;
    20     }
    21     return -1;
    22 }
    //离散对数,解 a^x%mod=b,返回最小的
     1 void gcd(LL a, LL b, LL &d, LL &x, LL &y)
     2 {
     3     if (!b)
     4     {
     5         d = a;
     6         x = 1;
     7         y = 0;
     8     }
     9     else
    10     {
    11         gcd(b, a % b, d, y, x);
    12         y -= a / b * x;
    13     }
    14 }
    //拓展欧几里得求 ax+by=g=gcd(a,b)的解(x,y),通解为(x+kb/g,y+ka/g) //则 ax+by=c(g|c) 的解为(xc/g,yc/g)
     1 LL equation(LL a, LL b, LL r, LL &x, LL &y)
     2 {
     3     LL g;
     4     gcd(a, b, g, x, y); //求出 ax+by==g
     5     if (r % g)
     6         return 0; //无解
     7     x *= r / g;
     8     y *= r / g;
     9     return g > 0 ? g : -g; //返回 gcd
    10 }
    //解方程 ax+by==r,r==0时按需特殊处理 通解(x+k*b/g,y-k*a/g);
     1 int a, b, c, x0, x2, y0, y2;
     2 LL solve(LL a, LL b, LL c, LL x0, LL x2, LL y0, LL y2)
     3 {
     4     if (a < 0 && b < 0)
     5         a = -a, b = -b, c = -c;
     6     if (!b || a < 0 && b > 0)
     7         swap(a, b), swap(x0, y0), swap(x2, y2);
     8     if (!a && !b)
     9     {
    10         if (c)
    11             return 0;
    12         return (x2 - x0 + 1LL) * (y2 - y0 + 1LL);
    13     }
    14     if (!a)
    15     {
    16         if (c % b || y0 > -c / b || y2 < -c / b)
    17             return 0;
    18         return x2 - x0 + 1;
    19     }
    20     LL g, x, y;
    21     g = equation(a, b, -c, x, y);
    22     if (!g)
    23         return 0;
    24 
    25     LL aa = abs(a / g), bb = abs(b / g);
    26     x0 += ((x % bb + bb) % bb - (x0 % bb + bb) % bb + bb) % bb;
    27     x2 -= ((x2 % bb + bb) % bb - (x % bb + bb) % bb + bb) % bb;
    28     y0 += ((y % aa + aa) % aa - (y0 % aa + aa) % aa + aa) % aa;
    29     y2 -= ((y2 % aa + aa) % aa - (y % aa + aa) % aa + aa) % aa;
    30     if (x0 > x2 || y0 > y2)
    31         return 0;
    32     x0 = (-c - a * x0) / b;
    33     //a*x0注意溢出
    34     x2 = (-c - a * x2) / b;
    35     if (b > 0)
    36         swap(x0, x2);
    37     x0 = max(x0, y0);
    38     x2 = min(x2, y2);
    39     if (x0 > x2)
    40         return 0;
    41     return (x2 - x0) / aa + 1;
    42 }
    //ax+by+c=0 在 x0<=x<=x2 y0<=y<=y2范围内的整数解个数
     1 LL multi_equation(int n, int *r, int *m)
     2 {
     3     LL x, y, g, lcm, ans;
     4     lcm = m[0];
     5     ans = r[0];
     6     for (int i = 1; i < n; i++)
     7     {
     8         g = equation(lcm, -m[i], r[i] - ans, x, y);
     9         if (!g)
    10             return -1; //无解
    11         ans += x * lcm;
    12         lcm *= m[i] / g;
    13         ans %= lcm;
    14         //注意溢出
    15     }
    16     if (ans % lcm == 0)
    17         return lcm; //结果为 0时答案为 lcm
    18     return (ans + lcm) % lcm;
    19 }
    //类似中国剩余定理,可处理 m数组不互质的情况
    1 LL Inv(LL a, LL n) //O(logn)
    2 {
    3     LL g, x, y;
    4     gcd(a, n, g, x, y);
    5     return g == 1 ? (x + n) % n : -1;
    6 }
    //逆元求(a^b-c)/d%p时当 a^b-c==0时(a^b-c)*inv(d)==0会出错,需特殊处理
    //逆元,a/b%mod=a*b^-1%mod,f(x)=inv(x,mod)或 f(x)=quick_mod(x,mod-2,mod),mod需是质数
    //若 a,m互质,r=a/b%m=a*inv(b)%m,否则 r=a/b%m=a%(m*b)/b 可以算 a%(m*b)但算不了 a/b时用
    //mod为素数线性求逆元:inv(x)=-(mod/x)*inv(mod%x)=(mod– mod/x)*inv(mod%x)%mod
     1 LL quick_mod(LL t, LL n)
     2 {
     3     t %= mod;
     4     LL ans = 1;
     5     while (n)
     6     {
     7         if (n & 1)
     8             ans = ans * t % mod;
     9         t = t * t % mod;
    10         n >>= 1;
    11     }
    12     return ans;
    13 }
    //t^n%mod二分快速幂 O(log(n))
     1 LL fac[N];
     2 LL Inv(LL x)
     3 {
     4     return quick_mod(x, mod - 2);
     5 }
     6 void init()
     7 {
     8     //要先执行
     9     fac[0] = 1;
    10     for (int i = 1; i < N; i++)
    11         fac[i] = fac[i - 1] * i % mod;
    12     //阶乘模
    13 }
    14 //若 mod不为质数且 n*m较小可以考虑打 n*m的 C[n][m]二维表
    15 LL Cnm(int n, int m)
    16 {
    17     if (n < m || n < 0 || m < 0)
    18         return 0;
    19     return fac[n] * Inv(fac[m] * fac[n - m] % mod) % mod;
    20 }
    //求 n,m小于 N的组合数 C(n,m)%mod O(nlogn)
     1 LL Lucas(LL n, LL m)
     2 {
     3     if (n < m || n < 0 || m < 0)
     4         return 0;
     5     LL ans = 1;
     6     while (n && m)
     7     {
     8         ans = ans * Cnm(n % mod, m % mod) % mod; //这儿 Cnm的求逆不可先处理,会超时
     9         n /= mod;
    10         m /= mod;
    11     }
    12     return ans;
    13 }
    14 LL Lucas(LL n, LL m)
    15 //递归
    16 {
    17     if (m == 0)
    18         return 1;
    19     else
    20         return (Cnm(n % mod, m % mod) * Lucas(n / mod, m / mod)) % mod;
    21 }
    /*首先给出这个 Lucas定理:
    A、B是非负整数,p是质数。AB写成 p进制:A=a[n]a[n-1]...a[0],B=b[n]b[n-1]...b[0]。
    则组合数 C(A,B)与 C(a[n],b[n])*C(a[n-1],b[n-1])*...*C(a[0],b[0]) mod p同余
    即:Lucas(n,m,p)=c(n%p,m%p)*Lucas(n/p,m/p,p) */
    //求 C(n,m)%mod mod最大为 10^5。a,b可以很大!
      1 //对每个数分解质因子和次幂
      2 int pn, p[N], vis[N], d[N][10], e[N][10], dn[N];
      3 void init()
      4 {
      5     pn = 1;
      6     memset(vis, 0, sizeof(vis));
      7     memset(e, 0, sizeof(e));
      8     memset(dn, 0, sizeof(dn));
      9     for (int i = 2; i < N; i++)
     10         if (!vis[i])
     11         {
     12             p[pn] = i;
     13             for (int j = i; j < N; j += i)
     14             {
     15                 vis[j] = 1;
     16                 int &n = dn[j];
     17                 d[j][n] = i;
     18                 int x = j;
     19                 while (x % i == 0)
     20                     x /= i, e[j][n]++;
     21                 n++;
     22             }
     23             vis[i] = pn++;
     24         }
     25 }
     26 
     27 int c[N];
     28 inline void add(int n, int x)
     29 {
     30     if (!x)
     31         return;
     32     for (int i = 0; i < dn[n]; i++)
     33     {
     34         int id = vis[d[n][i]];
     35         c[id] += x * e[n][i];
     36     }
     37 }
     38 //x个组合数相乘求模,mod可不为质数,n不能太大,复杂度 x*log(n)+n*log(p)
     39 int bit[N];
     40 inline int sum(int x)
     41 {
     42     int res = 0;
     43     while (x > 0)
     44         res += bit[x], x -= x & -x;
     45     return res;
     46 }
     47 inline void update(int x, int y, int d)
     48 {
     49     if (!d)
     50         return;
     51     while (x <= n)
     52         bit[x] += d, x += x & -x;
     53     y++;
     54     while (y <= n)
     55         bit[y] -= d, y += y & -y;
     56 }
     57 int vv[n];
     58 inline void Cnm(int n, int m)
     59 {
     60     vv[n]++;
     61     vv[m]--;
     62     vv[n - m]--;
     63 }
     64 LL cal()
     65 {
     66     LL ans = 1;
     67     for (int i = 2; i <= n; i++)
     68         update(1, i, vv[i]);
     69     for (int i = 2; i <= n; i++)
     70         add(i, sum(i));
     71     for (int i = 1; i < pn && p[i] <= n; i++)
     72         if (c[i])
     73             ans = ans * quick_mod(p[i], c[i]) % mod;
     74     return ans;
     75 }
     76 
     77 //单个组合数取 mod,mod可不为质数 复杂度 n*log(p)
     78 LL Cnm(int n, int m)
     79 {
     80     if (n < m || n < 0 || m < 0)
     81         return 0;
     82     m = min(m, n - m);
     83     LL ans = 1;
     84     memset(c, 0, sizeof(c));
     85     for (int i = n, j = m; j > 0; i--, j--)
     86     {
     87         add(i, 1);
     88         add(j, -1);
     89     }
     90     for (int i = 1; i < pn; i++)
     91         if (c[i])
     92             ans = ans * quick_mod(p[i], c[i], mod) % mod;
     93     return ans;
     94 }
     95 int c[N], vv[N];
     96 inline void add(int n, int x)
     97 {
     98     if (!x)
     99         return;
    100     for (int i = 0; i < dn[n]; i++)
    101     {
    102         int id = vis[d[n][i]];
    103         c[id] += x * e[n][i];
    104     }
    105 }
    大组合数求模
     1 int c[N][N], fac[N], part[N][N];
     2 void init()
     3 {
     4     memset(c, 0, sizeof(c));
     5     c[0][0] = fac[0] = 1;
     6     for (int i = 1; i < N; i++) //杨辉三角 Cnm递推
     7     {
     8         fac[i] = (LL)fac[i - 1] * i % mod;
     9         c[i][0] = 1;
    10         for (int j = 1; j <= i; j++)
    11             c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;
    12     }
    13     //集合划分,part[i][j]表示 i个不同的元素划分成 j个相同组(i个不同球放到 j个相同盒子,不能有空盒,
    14     //可以有空盒的为前缀和),递推式 S(n,m)=S(n-1,m-1)+m*S(n-1,m)
    15     memset(part, 0, sizeof(part));
    16     part[1][1] = 1;
    17     for (int i = 2; i < N; i++)
    18         for (int j = 1; j <= i; j++)
    19             part[i][j] = (part[i - 1][j] * j + part[i - 1][j - 1]) % mod;
    20 }
    //集合划分,杨辉三角递推
     1 typedef unsigned int UI;
     2 const int HASH=100007;
     3 char e[N][20],w[N][20];
     4 struct Hash
     5 {
     6     int *head, *next, n;
     7     Hash()
     8     {
     9         head = new int[HASH];
    10         next = new int[N];
    11         n = 1;
    12         memset(head, 0, sizeof(head));
    13     }
    14     ~Hash()
    15     {
    16         delete[] head;
    17         delete[] next;
    18     }
    19     UI hash(char *s)
    20     {
    21         UI ans = 0;
    22         for (int i = 0; s[i]; i++)
    23             ans = s[i] + ans * 101;
    24         return ans % HASH;
    25     }
    26     int hash(int s) { return s % HASH; }
    27     bool cmp(char *a, char *b) { return !strcmp(a, b); }
    28     bool cmp(int a, int b) { return a == b; }
    29     bool insert(int s)
    30     {
    31         int h = hash(e[s]);
    32         int u = head[h];
    33         while (u)
    34         {
    35             //当插入元素中不会有重复时可不要此循环
    36             if (cmp(e[u], e[s]))
    37                 return 0;
    38             u = next[u];
    39         }
    40         next[s] = head[h];
    41         head[h] = s;
    42         return 1;
    43     }
    44     int find(char *s)
    45     {
    46         int h = hash(s);
    47         int u = head[h];
    48         while (u)
    49         {
    50             if (cmp(e[u], s))
    51                 return u;
    52             u = next[u];
    53         }
    54         return 0;
    55     }
    56 };
    //hash模板,当 e数组较大时要开到外面,可用于求四元方程 a+b+c+d=0的解,状态标记 //可用于单词表查找,查找单词表中某单词是否可以由另两个单词合成(1~len-1拆分查找)
     1 const LL base=1e18;
     2 const LL MOD=1e9;
     3 struct int128
     4 {
     5     LL a, b;
     6     //a为低位
     7     int128(LL x = 0, LL y = 0)
     8     {
     9         a = x;
    10         b = y;
    11     }
    12     int128 operator+(const int128 &x) const
    13     {
    14         return int128(a + x.a, b + x.b);
    15     }
    16     int128 operator-(const int128 &x) const
    17     {
    18         return int128(a - x.a, b - x.b);
    19     }
    20     int128 operator*(const int128 &x) const //相乘结果范围为[-(2^63)*1e18,(2^63-1)*1e18]
    21     {
    22         LL x0 = a % MOD, x1 = a / MOD;
    23         LL y0 = x.a % MOD, y1 = x.a / MOD;
    24         int128 c;
    25         c.a = x0 * y0;
    26         c.b = x1 * y1;
    27         c.a += x0 * y1 % MOD * MOD;
    28         c.b += x0 * y1 / MOD;
    29         c.a += x1 * y0 % MOD * MOD;
    30         c.b += x1 * y0 / MOD;
    31         return c;
    32     }
    33     int128 operator/(const LL &x) const
    34     {
    35         LL ans, r, t = a, e = base / 10;
    36         ans = b / x;
    37         r = b % x;
    38         for (int i = 17; i >= 0; i--, e /= 10)
    39         {
    40             ans = ans * 10 + (r * 10 + t / e) / x;
    41             r = (r * 10 + t / e) % x;
    42             t %= e;
    43         }
    44         return int128(ans);
    45     }
    46     int128 operator%(const LL &x) const
    47     {
    48         LL ans, t = a, e = base / 10;
    49         ans = b % x;
    50         for (int i = 17; i >= 0; i--, e /= 10)
    51         {
    52             ans = (ans * 10 + t / e) % x;
    53             t %= e;
    54         }
    55         return int128(ans);
    56     }
    57 };
    58 
    59  
    60 void print(int128 x)
    61 {
    62     if (x.b)
    63         printf("%lld%018lld", x.b, x.a);
    64     else
    65         printf("%lld", x.a);
    66 }
    //大整数相关 //手动模拟__int28
     1 const int base=10;
     2 int largediv(char*a,char*b,char*ans)
     3 {
     4     int j = 0, la = strlen(a), lb = strlen(b), l = 0;
     5     while (la - j >= lb)
     6     {
     7         int t = 0;
     8         while ((j > 0 && a[j - 1] != '0') || strncmp(a + j, b, lb) >= 0)
     9         {
    10             t++;
    11             for (int i = lb - 1; i >= 0; i--)
    12             {
    13                 a[i + j] -= b[i] - '0';
    14                 if (a[i + j] < '0')
    15                 {
    16                     a[i + j] += base;
    17                     a[i + j - 1]--;
    18                 }
    19             }
    20         }
    21         j++;
    22         ans[l++] = t + '0';
    23         if (l == 0 && ans[l] == '0')
    24             l--;
    25     }
    26     if (!l)
    27         ans[l++] = '0';
    28     ans[l] = 0;
    29     int x = 0;
    30     while (x < la && a[x] == '0')
    31         x++;
    32     if (x == la)
    33         x--;
    34     return x;
    35 }
    //大整数除法或求模,商为 ans(可能会有一个前导 0,输出要处理,注意结果为 0),余数为 a+x
     1 struct Fraction
     2 {
     3     LL num;
     4     LL den;
     5     Fraction(LL num = 0, LL den = 1)
     6     {
     7         if (den < 0)
     8         {
     9             num = -num;
    10             den = -den;
    11         }
    12         assert(den != 0);
    13         LL g = __gcd(abs(num), den);
    14         this->num = num / g;
    15         this->den = den / g;
    16     }
    17     Fraction operator+(const Fraction &x) const
    18     {
    19         return Fraction(num * x.den + den * x.num, den * x.den);
    20     }
    21     Fraction operator-(const Fraction &x) const
    22     {
    23         return Fraction(num * x.den - den * x.num, den * x.den);
    24     }
    25     Fraction operator*(const Fraction &x) const
    26     {
    27         return Fraction(num * x.num, den * x.den);
    28     }
    29     Fraction operator/(const Fraction &x) const
    30     {
    31         return Fraction(num * x.den, den * x.num);
    32     }
    33     bool operator<(const Fraction &x) const
    34     {
    35         return num * x.den < den * x.num;
    36     }
    37     bool operator==(const Fraction &x) const
    38     {
    39         return num * x.den == den * x.num;
    40     }
    41 };
    //分数类
      1 struct bigint
      2 {
      3     int *a;
      4     //a[0]存长度
      5     static const int maxlen = 1e4 + 10;
      6     static const int basel = 8;
      7     static const int base = 1e9;
      8     bigint() { a = new int[maxlen]; }
      9     ~bigint() { delete[] a; }
     10     //输出大整数 a,base不一样时记得改 04d
     11     void print()
     12     {
     13         int n = a[0];
     14         printf("%d", a[--n]);
     15         for (--n; n; n--)
     16             printf("%09d", a[n]);
     17         printf("
    ");
     18     }
     19     //将正序的字符串 x转为 10^(basel+1)进制逆序大整数 a
     20     bigint &trans(char *x)
     21     {
     22         int lx = strlen(x);
     23         int &la = a[0] = 1;
     24         for (int i = lx - 1; i >= 0;)
     25         {
     26             int t = 0, k = i - (basel < i ? basel : i);
     27             for (int j = k; j <= i; j++)
     28                 t = t * 10 + x[j] - '0';
     29             i = k - 1;
     30             a[la++] = t;
     31         }
     32         return *this;
     33     }
     34     bool equal(int x) { return a[0] == 2 && a[1] == x; }
     35     //<base的整数转为大整数
     36     bigint &intTobig(int x)
     37     {
     38         a[0] = 2;
     39         a[1] = x;
     40         return *this;
     41     }
     42     bigint &copy(bigint & b)
     43     {
     44         memcpy(a, b.a, sizeof(a[0]) * b.a[0]);
     45         return *this;
     46     }
     47     void swap(bigint & b)
     48     {
     49         int *tmp = a;
     50         a = b.a;
     51         b.a = tmp;
     52     }
     53     bigint &add(bigint & tb, bigint & tans)
     54     {
     55         int *b = tb.a, *ans = tans.a;
     56         int l = max(a[0], b[0]);
     57         memset(ans, 0, sizeof(a[0]) * (l + 1));
     58         for (int i = 1; i < l; i++)
     59         {
     60             if (i >= a[0])
     61                 a[i] = 0;
     62             if (i >= b[0])
     63                 b[i] = 0;
     64             ans[i] += a[i] + b[i];
     65             ans[i + 1] += ans[i] / base;
     66             ans[i] %= base;
     67         }
     68         ans[0] = (ans[l] ? l + 1 : l);
     69         return tans;
     70     }
     71     bigint &minus(bigint & tb, bigint & tans)
     72     {
     73         int *b = tb.a, *ans = tans.a;
     74         memset(ans, 0, sizeof(int) * (a[0] + 1));
     75         for (int i = 1; i < a[0]; i++)
     76         {
     77             if (i >= b[0])
     78                 b[i] = 0;
     79             ans[i] += a[i] - b[i];
     80             if (ans[i] < 0)
     81             {
     82                 ans[i] += base;
     83                 ans[i + 1]--;
     84             }
     85         }
     86         ans[0] = a[0];
     87         while (ans[0] > 2 && !ans[ans[0] - 1])
     88             ans[0]--;
     89         return tans;
     90     }
     91     bigint &mul(bigint & tb, bigint & tans)
     92     {
     93         int *b = tb.a, *ans = tans.a;
     94         memset(ans, 0, sizeof(int) * (a[0] + b[0]));
     95         for (int i = 1; i < a[0]; i++)
     96         {
     97             for (int j = 1; j < b[0]; j++)
     98             {
     99                 LL t = ans[i + j - 1] + (LL)a[i] * b[j];
    100                 ans[i + j] += t / base;
    101                 ans[i + j - 1] = t % base;
    102             }
    103         }
    104         int &l = ans[0];
    105         l = a[0] + b[0] - 2;
    106 
    107         while (l > 1 && !ans[l])
    108             l--;
    109         l++;
    110         return tans;
    111     }
    112     //大整数除法或求模,被除数<=Base
    113     int div(int b, bigint &tans)
    114     {
    115         int *ans = tans.a;
    116         ans[0] = 1;
    117         ans[ans[0]++] = 0;
    118         LL sum = 0, first = 1;
    119         for (int i = a[0] - 1; i > 0; i--)
    120         {
    121             sum = sum * base + a[i];
    122             if (sum < b && first)
    123                 continue;
    124             if (first)
    125             {
    126                 first = 0;
    127                 ans[0] = i + 1;
    128             }
    129             ans[i] = sum / b;
    130             sum %= b;
    131         }
    132         return sum;
    133     }
    134     bool less(bigint & x) //this<x
    135     {
    136         if (x.a[0] != a[0])
    137             return a[0] < x.a[0];
    138         for (int i = a[0] - 1; i > 0; i--)
    139             if (a[i] != x.a[i])
    140                 return a[i] < x.a[i];
    141         return 0;
    142     }
    143 };
    //大整数类
     1 int d[2000],dn,c[2000];
     2 void fac(int n)//找出所有约数
     3 {
     4     dn = 0;
     5     for (int i = 1; i * i <= n; i++)
     6         if (n % i == 0)
     7         {
     8             d[dn++] = i;
     9             if (i * i != n)
    10                 d[dn++] = n / i;
    11         }
    12     sort(d, d + dn);
    13 }
    14 LL polya(int n)
    15 {
    16     fac(n);
    17     memset(c, 0, sizeof(c));
    18     for (int i = 0; i < dn; i++) //容斥求所有约数的欧拉函数
    19     {
    20         c[i] += d[i];
    21         for (int j = i + 1; j < dn; j++)
    22             if (d[j] % d[i] == 0)
    23                 c[j] -= c[i];
    24     }
    25     LL ans = 0;
    26     for (int i = 0; i < dn; i++)
    27     {
    28         int x = n / d[i];
    29         ans = (ans + (LL)c[i] * mar_quick(x, 2, 1)) % mod; //计算 x 个循环节的置换有多少种方案,polya 定理中
    30         为 m ^ x
    31     }
    32     ans = (ans * Inv(n)) % mod;
    33     return ans;
    34 }
    //polya定理
     1 int d[2000],phi[2000],dn,p[20],pn,e[20];
     2 void facdiv(int n) //质因分解成 n=p[0]^e[0] * p[1]^e[1] * ... *p[pn-1]^e[pn-1]
     3 {
     4     pn = 0;
     5     //for(int j=0,i=prime[0];i*i<=n;i=prime[++j]) if(n%i==0)
     6     //筛出质数表加速质因分解
     7     for (int i = 2; i * i <= n; i++)
     8         if (n % i == 0)
     9         {
    10             p[pn] = i;
    11             e[pn] = 0;
    12             while (n % i == 0)
    13                 n /= i, e[pn]++;
    14             pn++;
    15         }
    16     if (n != 1)
    17         p[pn] = n, e[pn++] = 1;
    18 }
    //d为约数数组,phi[i]为第 i个约数的欧拉函数,p为 n分解出来的素数数组,e为次幂数组
     1 void GetDivisorPhi() //根据上面的基因分解算出所有约数的欧拉函数(与 d[i]互质的数的个数)
     2 {
     3     dn = 1;
     4     d[0] = 1;
     5     phi[0] = 1;
     6     for (int i = 0; i < pn; i++)
     7     {
     8         int num = dn;
     9         for (int j = 0; j < num; j++)
    10         {
    11             phi[dn] = phi[j] * (p[i] - 1);
    12             d[dn] = d[j] * p[i];
    13             dn++;
    14             for (int k = 2; k <= e[i]; k++)
    15             {
    16                 phi[dn] = phi[dn - 1] * p[i];
    17                 d[dn] = d[dn - 1] * p[i];
    18                 dn++;
    19             }
    20         }
    21     }
    22 }
    //根据上面的基因分解算出所有约数的欧拉函数(与 d[i]互质的数的个数)
     1 const int S=20;//随机算法判定次数,S越大,判错概率越小
     2 //计算 (a*b)%c. a,b都是 LL的数,直接相乘可能溢出的
     3 // a,b,c <2^63
     4 LL multi_mod( LL x , LL y ,LL mod)
     5 {
     6     return (x * y - (LL)(x / (long double)mod * y + 1e-3) * mod + mod) % mod;
     7 }
     8 //快速幂,计算 x^n %c
     9 LL quick_mod(LL t,LL n,LL mod)
    10 {
    11     t %= mod;
    12     LL ans = 1;
    13     while (n)
    14     {
    15         if (n & 1)
    16             ans = multi_mod(ans, t, mod);
    17         t = multi_mod(t, t, mod);
    18         n >>= 1;
    19     }
    20     return ans;
    21 }
    22 
    23  
    24 //以 a为基,n-1=x*2^t
    25 a^(n-1)=1(mod n) 验证 n是不是合数
    26 //一定是合数返回 true,不一定返回 false
    27 bool check(LL a,LL n,LL x,LL t)
    28 {
    29     LL ans = quick_mod(a, x, n);
    30     LL last = ans;
    31     for (int i = 1; i <= t; i++)
    32     {
    33         ans = multi_mod(ans, ans, n);
    34         if (ans == 1 && last != 1 && last != n - 1)
    35             return true; //合数
    36         last = ans;
    37     }
    38     if (ans != 1)
    39         return true;
    40     return false;
    41 }
    42 // Miller_Rabin()算法素数判定
    43 //是素数返回 true.(可能是伪素数,但概率极小)
    44 //合数返回 false;
    45 bool Miller_Rabin(LL n)
    46 {
    47     if (n < 2)
    48         return false;
    49     if (n == 2)
    50         return true;
    51     if ((n & 1) == 0)
    52         return false; //偶数
    53     LL x = n - 1;
    54     LL t = 0;
    55     while ((x & 1) == 0)
    56     {
    57         x >>= 1;
    58         t++;
    59     }
    60     for (int i = 0; i < S; i++)
    61     {
    62         LL a = rand() % (n - 1) + 1;
    63         if (check(a, n, x, t))
    64             return false; //合数
    65     }
    66     return true;
    67 }
    // Miller_Rabin 算法进行素数测试 //速度快,而且可以判断 <2^63的数
     1 LL fac[100];//质因数分解结果(刚返回时是无序的)
     2 int tol;//质因数的个数。数组小标从 0开始
     3 LL gcd(LL a,LL b)
     4 {
     5     if (a == 0)
     6         return 1;
     7     if (a < 0)
     8         return gcd(-a, b);
     9     while (b)
    10     {
    11         LL t = a % b;
    12         a = b;
    13         b = t;
    14     }
    15     return a;
    16 }
    17 
    18  
    19 LL Pollard_rho(LL x,LL c)
    20 {
    21     LL i = 1, k = 2;
    22     LL x0 = rand() % x;
    23     LL y = x0;
    24     while (1)
    25     {
    26         i++;
    27         x0 = (multi_mod(x0, x0, x) + c) % x;
    28         LL d = gcd(y - x0, x);
    29         if (d != 1 && d != x)
    30             return d;
    31         if (y == x0)
    32             return x;
    33         if (i == k)
    34             y = x0, k += k;
    35     }
    36 }
    37 //对 n进行素因子分解,分解后的因子不是有序的,要 sort
    38 void findfac(LL n)
    39 {
    40     if (n == 1)
    41         return;
    42     if (Miller_Rabin(n)) //素数
    43     {
    44         fac[tol++] = n;
    45         return;
    46     }
    47     LL p = n;
    48     while (p >= n)
    49         p = Pollard_rho(p, rand() % (n - 1) + 1);
    50     findfac(p);
    51     findfac(n / p);
    52 }
    //pollard_rho 算法进行质因数分解,复杂度比 sqrt(n)低
     1 LL multi_mod(LL a,LL b,LL mod)//a,b传过来的要是正数
     2 {
     3     LL ans = 0;
     4     a %= mod;
     5     b %= mod;
     6     while (b)
     7     {
     8         if (b & 1)
     9             ans = ans + a;
    10         if (ans >= mod)
    11             ans -= mod;
    12         a <<= 1;
    13         if (a >= mod)
    14             a -= mod;
    15         b >>= 1;
    16     }
    17     return ans;
    18 }
    //模乘法,模拟二进制乘法求模,在 long long*long long求模的情况下不溢出 O(64)
    1 LL multi_mod( LL x , LL y ,LL mod)
    2 {
    3     return (x * y - (LL)(x / (long double)mod * y + 1e-3) * mod + mod) % mod;
    4 }
    //比上面的模乘法快,并不懂原理
     1 //multi_mod 中过多的传参会耗费大量时间,不爆 long long 的话最好写成 a*b%mod
     2 //如果精度超过 double 可以用 NTT 求多个 P,再用中国剩余定理算回去
     3 //f(i)=sigma{a[j]*b[i-j],0<=i<n}
     4 //const LL P = ( 1LL << 55 ) * 5 + 1 ;
     5 //const LL G = 6 ;
     6 const int P =479<<21|1;
     7 //const int P1=119<<23|1;//费马质数,P-1 能整除 2^n
     8 const int G = 3; //原根,最小的数满足 G^(P-1)==1
     9 const int NUM = 30;
    10 LL wn[NUM];
    11 LL x[N*4],y[N*4];
    12 void GetWn()
    13 {
    14     for (int i = 0; i < NUM; i++)
    15     {
    16         int t = 1 << i;
    17         wn[i] = quick_mod(G, (P - 1) / t);
    18     }
    19 }
    20 void NTT(LL *a,int len,bool rev)
    21 {
    22     for (int i = 1, j, t, k; i < len; i++)
    23     {
    24         for (k = len >> 1, t = i, j = 0; k; k >>= 1, t >>= 1)
    25             j = j << 1 | t & 1;
    26         if (i < j)
    27             swap(a[i], a[j]);
    28     }
    29     for (int s = 2, ds = 1, id = 1; s <= len; ds = s, s <<= 1, id++)
    30     {
    31         for (int k = 0; k < len; k += s)
    32         {
    33             LL w = 1, t;
    34             for (int i = k; i < k + ds; i++)
    35             {
    36                 a[i + ds] = (a[i] - (t = multi_mod(a[i + ds], w)) + P) % P;
    37                 a[i] = (a[i] + t) % P;
    38                 w = multi_mod(w, wn[id]);
    39             }
    40         }
    41     }
    42     if (rev)
    43     {
    44         for (int i = 1; i<len>> 1; i++)
    45             swap(a[i], a[len - i]);
    46         LL inv = quick_mod(len, P - 2);
    47         for (int i = 0; i < len; i++)
    48             a[i] = multi_mod(a[i], inv);
    49     }
    50 }
    51 void Conv(LL *a, LL *b, int n)
    52 {
    53     NTT(a, n, 0);
    54     NTT(b, n, 0);
    55     for (int i = 0; i < n; i++)
    56         a[i] = multi_mod(a[i], b[i]);
    57     NTT(a, n, 1);
    58 }
    //快速数论变换 NTT,得到的多项式的每一位的结果已经模了 P //不比 FFT 快,因为求模花的时间较多
     1 const double pi=acos(-1);
     2 struct cplx
     3 {
     4     //复数类/多项式/大整数
     5     double r, i;
     6     cplx(double r = 0, double i = 0) : r(r), i(i) {}
     7     cplx operator+(const cplx &a) const
     8     {
     9         return cplx(r + a.r, i + a.i);
    10     }
    11     cplx operator-(const cplx &a) const
    12     {
    13         return cplx(r - a.r, i - a.i);
    14     }
    15     cplx operator*(const cplx &a) const
    16     {
    17         return cplx(r * a.r - i * a.i, r * a.i + i * a.r);
    18     }
    19 };
    20 //快速傅里叶变换 FFT(nlogn)
    21 //len = 2^M,reverse F[i] with F[j] j为 i二进制反转
    22 void rader(cplx *f,int len)
    23 {
    24     int j = len >> 1;
    25     for (int i = 1; i < len - 1; ++i)
    26     {
    27         if (i < j)
    28             swap(f[i], f[j]); // reverse
    29         int k = len >> 1;
    30         while (j >= k)
    31         {
    32             j -= k;
    33             k >>= 1;
    34         }
    35         if (j < k)
    36             j += k;
    37     }
    38 }
    39 //做 FFT,len必须为 2^k形式,on==1时是 DFT,on==-1时是 IDFT
    40 void FFT(cplx *f,int len,int t)
    41 {
    42     rader(f, len);
    43     for (int h = 2; h <= len; h <<= 1)
    44     {
    45         cplx wn(cos(-t * 2 * pi / h), sin(-t * 2 * pi / h));
    46         for (int j = 0; j < len; j += h)
    47         {
    48             cplx e(1, 0); //旋转因子
    49             for (int k = j; k < j + h / 2; ++k)
    50             {
    51                 cplx u = f[k];
    52 
    53                 cplx v = e * f[k + h / 2];
    54                 f[k] = u + v;
    55                 f[k + h / 2] = u - v;
    56                 e = e * wn;
    57             }
    58         }
    59     }
    60     if (t == -1)
    61         for (int i = 0; i < len; ++i)
    62             f[i].r /= len; //IDFT
    63 }
    64 //传入 a,b之前需将 a,b的长度处理为 len=2^k,a,b数组需开到原长度的 3-4倍,变换结果为 a数组
    65 void Conv(cplx *a,cplx *b,int len) //求卷积
    66 {
    67     FFT(a, len, 1);
    68     FFT(b, len, 1);
    69     for (int i = 0; i < len; ++i)
    70         a[i] = a[i] * b[i];
    71     FFT(a, len, -1);
    72 }
    //快速傅里叶变换 FFT(nlogn)
      1 const int N = 5e6+2;
      2 bool np[N];
      3 int p[N],pi[N];
      4 int getprime()
      5 {
      6     //pi[i]表示不超过 i的质数个数,p存素数
      7     int cnt = 0;
      8     np[0] = np[1] = true;
      9     pi[0] = pi[1] = 0;
     10     for (int i = 2; i < N; ++i)
     11     {
     12         if (!np[i])
     13             p[++cnt] = i;
     14         for (int j = 1; j <= cnt && i * p[j] < N; ++j)
     15         {
     16             np[i * p[j]] = true;
     17         }
     18         pi[i] = cnt;
     19     }
     20     return cnt;
     21 }
     22 const int M = 7;
     23 const int PM = 2*3*5*7*11*13*17;
     24 int phi[PM+1][M+1],sz[M+1];
     25 void init()
     26 {
     27     getprime();
     28     sz[0] = 1;
     29     for (int i = 0; i <= PM; ++i)
     30         phi[i][0] = i;
     31     for (int i = 1; i <= M; ++i)
     32     {
     33         sz[i] = p[i] * sz[i - 1];
     34         for (int j = 1; j <= PM; ++j)
     35         {
     36             phi[j][i] = phi[j][i - 1] - phi[j / p[i]][i - 1];
     37         }
     38     }
     39 }
     40 
     41  
     42 int sqrt2(LL x)
     43 {
     44     LL r = (LL)sqrt(x - 0.1);
     45     while (r * r <= x)
     46         ++r;
     47     return int(r - 1);
     48 }
     49 int sqrt3(LL x)
     50 {
     51     LL r = (LL)cbrt(x - 0.1);
     52     while (r * r * r <= x)
     53         ++r;
     54     return int(r - 1);
     55 }
     56 LL getphi(LL x,int s)
     57 {
     58     if (s == 0)
     59         return x;
     60     if (s <= M)
     61         return phi[x % sz[s]][s] + (x / sz[s]) * phi[sz[s]][s];
     62     if (x <= p[s] * p[s])
     63         return pi[x] - s + 1;
     64     if (x <= p[s] * p[s] * p[s] && x < N)
     65     {
     66         int s2x = pi[sqrt2(x)];
     67         LL ans = pi[x] - (s2x + s - 2) * (s2x - s + 1) / 2;
     68         for (int i = s + 1; i <= s2x; ++i)
     69         {
     70             ans += pi[x / p[i]];
     71         }
     72         return ans;
     73     }
     74     return getphi(x, s - 1) - getphi(x / p[s], s - 1);
     75 }
     76 LL getpi(LL x)
     77 {
     78     //返回小于 x 的素数个数
     79     if (x < N)
     80         return pi[x];
     81     LL ans = getphi(x, pi[sqrt3(x)]) + pi[sqrt3(x)] - 1;
     82     for (int i = pi[sqrt3(x)] + 1, ed = pi[sqrt2(x)]; i <= ed; ++i)
     83         ans -= getpi(x / p[i]) - i + 1;
     84     return ans;
     85 }
     86 LL lehmer_pi(LL x)
     87 {
     88     if (x < N)
     89         return pi[x];
     90     int a = (int)lehmer_pi(sqrt2(sqrt2(x)));
     91     int b = (int)lehmer_pi(sqrt2(x));
     92     int c = (int)lehmer_pi(sqrt3(x));
     93     LL sum = getphi(x, a) + LL(b + a - 2) * (b - a + 1) / 2;
     94     for (int i = a + 1; i <= b; i++)
     95     {
     96         LL w = x / p[i];
     97         sum -= lehmer_pi(w);
     98         if (i > c)
     99             continue;
    100         LL lim = lehmer_pi(sqrt2(w));
    101         for (int j = i; j <= lim; j++)
    102         {
    103             sum -= lehmer_pi(w / p[j]) - (j - 1);
    104         }
    105     }
    106     return sum;
    107 
    108  
    109 }
    110 LL getans(LL x)
    111 { // x < 1e11
    112     LL ans = 0;
    113     //返回相乘不大于 x的质数对数
    114     for (int i = 1, ed = pi[sqrt2(x - 1)]; i <= ed; ++i)
    115         ans += lehmer_pi(x / p[i]) - i;
    116     return ans;
    117 }
    //算 1e11内质数个数,copy的,先要执行 init()函数
    1 void swap(int &a,int &b)
    2 {
    3     a ^= b;
    4     b ^= a;
    5     a ^= b;
    6 }
    //交换两个数
    1 struct node
    2 {
    3     int i, w;
    4     bool operator<(const node &a) const
    5     {
    6         return w > a.w;
    7     }
    8 };
    //优先队列结构体
     1 int prim()
     2 {
     3     //O(nlogn)
     4     memset(d, 0x3f, sizeof(d));
     5     memset(vis, 0, sizeof(vis));
     6     d[1] = 0;
     7     priority_queue<node> q;
     8     q.push(node{1, 0});
     9     while (!q.empty())
    10     {
    11         node u = q.top();
    12         q.pop();
    13         if (vis[u.i])
    14             continue;
    15         vis[u.i] = 1;
    16         for (vector<int>::iterator i = v[u.i].begin(), j = w[u.i].begin(); i != v[u.i].end(); i++, j++)
    17         {
    18             if (vis[*i] || d[*i] <= *j)
    19                 continue;
    20             d[*i] = *j;
    21             q.push(node{*i, d[*i]});
    22         }
    23     }
    24     int sum = 0;
    25     for (int i = 1; i <= n; i++)
    26         sum += d[i];
    27     return sum;
    28 }
    29 
    30  
    31 int prim()
    32 {
    33     //O(n^2)
    34     memset(d, 0x3f, sizeof(d));
    35     memset(vis, 0, sizeof(vis));
    36     d[1] = 0;
    37     for (int i = 2; i <= n; i++)
    38     {
    39         int x = -1;
    40         for (int j = 1; j <= n; j++)
    41             if (!vis[j] && (x == -1 || d[j] < d[x]))
    42                 x = j; //j要未作为过起点
    43         vis[x] = 1;
    44         for (vector<int>::iterator j = v[x].begin(), k = w[x].begin(); j != v[x].end(); j++, k++)
    45             if (!vis[*j] && *k < d[*j])
    46                 d[*j] = *k;
    47     }
    48     int sum = 0;
    49     for (int i = 1; i <= n; i++)
    50         sum += d[i];
    51     return sum;
    52 }
    //Prim加点法最小生成树
     1 struct maxMacth
     2 {
     3     int n;
     4     int vm[N], um[N];
     5     bool vis[N];
     6     vector<int> g[N];
     7     int dx[N], dy[N], dis;
     8     void init(int num)
     9     {
    10         n = num;
    11         memset(vm, -1, sizeof(vm));
    12         memset(um, -1, sizeof(um));
    13         for (int i = 0; i <= n; i++)
    14             g[i].clear();
    15     }
    16     void inserts(int u, int v)
    17     {
    18         g[u].push_back(v);
    19     }
    20     bool searchP()
    21     {
    22         queue<int> q;
    23         dis = INF;
    24         memset(dx, -1, sizeof(dx));
    25         memset(dy, -1, sizeof(dy));
    26         for (int i = 1; i <= n; i++)
    27             if (um[i] == -1)
    28             {
    29                 q.push(i);
    30                 dx[i] = 0;
    31             }
    32         while (!q.empty())
    33 
    34         {
    35             int u = q.front();
    36             q.pop();
    37             if (dx[u] > dis)
    38                 break;
    39             for (int i = 0; i < g[u].size(); i++)
    40             {
    41                 int v = g[u][i];
    42                 if (dy[v] == -1)
    43                 {
    44                     dy[v] = dx[u] + 1;
    45                     if (vm[v] == -1)
    46                         dis = dy[v];
    47                     else
    48                     {
    49                         dx[vm[v]] = dy[v] + 1;
    50                         q.push(vm[v]);
    51                     }
    52                 }
    53             }
    54         }
    55         return dis != INF;
    56     }
    57     bool dfs(int u)
    58     {
    59         for (int i = 0; i < g[u].size(); i++)
    60         {
    61             int v = g[u][i];
    62             if (!vis[v] && dy[v] == dx[u] + 1)
    63             {
    64                 vis[v] = 1;
    65                 if (vm[v] != -1 && dy[v] == dis)
    66                     continue;
    67                 if (vm[v] == -1 || dfs(vm[v]))
    68                 {
    69                     vm[v] = u;
    70                     um[u] = v;
    71                     return 1;
    72                 }
    73             }
    74         }
    75         return 0;
    76     }
    77     int maxMatch()
    78     {
    79         int res = 0;
    80         while (searchP())
    81         {
    82             memset(vis, 0, sizeof(vis));
    83             for (int i = 1; i <= n; i++)
    84                 if (um[i] == -1 && dfs(i))
    85                     res++;
    86         }
    87         return res;
    88     }
    89 }MM;
    //二分图最大匹配
     1 const int N=1e6+10;
     2 const int M=26;
     3 int ch[N][M];
     4 int val[N];
     5 int sz;
     6 void init()
     7 {
     8     sz = 1;
     9     memset(ch[0], 0, sizeof(ch[0]));
    10 }
    11 inline int idx(char c)
    12 {
    13     return c - 'a'; 
    14 }
    15 void insert(char *s,int v)
    16 {
    17     int u = 0, i;
    18     for (i = 0; s[i]; i++)
    19     {
    20         int c = idx(s[i]);
    21         if (!ch[u][c])
    22         {
    23             memset(ch[sz], 0, sizeof(ch[sz]));
    24             val[sz] = 0;
    25             ch[u][c] = sz++;
    26         }
    27         u = ch[u][c];
    28     }
    29     val[u] = v;
    30     //val[u]=max(val[u],i);//val记录长度
    31 }
    32 int f[N],last[N];//last数组连接着所有相同后缀结束的模板串
    33 void getFail()
    34 {
    35     queue<int> q;
    36     f[0] = 0;
    37     for (int c = 0; c < M; c++)
    38     {
    39         int u = ch[0][c];
    40         if (u)
    41         {
    42             f[u] = 0;
    43             q.push(u);
    44             last[u] = 0;
    45         }
    46     }
    47     while (!q.empty())
    48     {
    49         int r = q.front();
    50         q.pop();
    51         for (int c = 0; c < M; c++)
    52         {
    53             int u = ch[r][c];
    54             if (!u)
    55                 continue;
    56             q.push(u);
    57 
    58             int v = f[r];
    59             while (v && !ch[v][c])
    60                 v = f[v];
    61             f[u] = ch[v][c];
    62             last[u] = val[f[u]] ? f[u] : last[f[u]];
    63         }
    64     }
    65 }
    66 void print(int i,int j)//输出所有匹配位置
    67 {
    68     if (j)
    69     {
    70         //找到后的处理,i是结束位置,字符串长度或值为 val[i]
    71         print(i, last[j]);
    72     }
    73 }
    74 int find(char *T)
    75 {
    76     int j = 0, i = 0;
    77     for (; T[i]; i++)
    78     {
    79         int c = idx(T[i]);
    80         while (j && !ch[j][c])
    81             j = f[j];
    82         j = ch[j][c];
    83         if (val[j])
    84             print(i, j);
    85         else if (last[j])
    86             print(i, last[j]);
    87     }
    88     return i;
    89 }
    //AC自动机 //字符串字典树
     1 const int maxc=2;
     2 const int BIT=31;
     3 int ch[N<<5][maxc],si[N<<5];
     4 void init()
     5 {
     6     //每次建一棵新的字典树都要初始化
     7     memset(ch[0], 0, sizeof(ch[0]));
     8     si[0] = 1;
     9 }
    10 void insert(int s)
    11 {
    12     int u = 0;
    13     for (int i = BIT - 1; i >= 0; i--)
    14     {
    15         int c = (s & (1 << i) ? 1 : 0);
    16         if (!ch[u][c])
    17         {
    18             memset(ch[si[0]], 0, sizeof(ch[0]));
    19             si[si[0]] = 0;
    20             ch[u][c] = si[0]++;
    21         }
    22         u = ch[u][c];
    23         si[u]++;
    24     }
    25 }
    26 int find(int s)
    27 {
    28     int u = 0;
    29     for (int i = BIT - 1; i >= 0; i--)
    30     {
    31         int c = (s & (1 << i) ? 1 : 0);
    32         if (!ch[u][c] || si[ch[u][c]] <= 0)
    33             return 0;
    34         u = ch[u][c];
    35     }
    36     return 1;
    37 }
    38 bool erase(int s)
    39 {
    40     int u = 0;
    41     for (int i = BIT - 1; i >= 0; i--)
    42     {
    43         int c = (s & (1 << i) ? 1 : 0);
    44         if (!ch[u][c] || si[ch[u][c]] <= 0)
    45             return 0;
    46         u = ch[u][c];
    47         si[u]--;
    48     }
    49     return 1;
    50 }
    //二进制数字典树
     1 int ch[N*20][2],si[N*20];
     2 //1 bro 0 son
     3 char val[N*20];
     4 void init()
     5 {
     6     ch[0][0] = ch[0][1] = 0;
     7     si[0] = 1;
     8     val[0] = 0;
     9 }
    10 void insert(char *s)
    11 {
    12     int u = 0;
    13     for (int i = 0; s[i]; i++)
    14     {
    15         int v = ch[u][0];
    16         while (v && val[v] != s[i])
    17             v = ch[v][1];
    18         if (!v)
    19         {
    20             //链表头插
    21             int &t = si[0];
    22             ch[t][1] = ch[u][0];
    23 
    24             si[t] = ch[t][0] = 0;
    25             val[t] = s[i];
    26             v = ch[u][0] = t++;
    27         }
    28         u = v;
    29     }
    30     si[u] = 1;
    31 }
    32 bool find(char *s)
    33 {
    34     int u = 0;
    35     for (int i = 0; s[i]; i++)
    36     {
    37         for (u = ch[u][0]; u && val[u] != s[i]; u = ch[u][1])
    38             ;
    39         if (!u)
    40             return 0;
    41     }
    42     if (si[u])
    43         return 1;
    44     return 0;
    45 }
    46 //字符串哈希 H(i)=H(i+1)x+s[i],Hash(i,L)=H(i)-H(i+L)*x^L;
    47 int bfind()
    48 {
    49     int l = 1, r = n;
    50     while (l < r)
    51     {
    52         int mid = r - (r - l) / 2;
    53         if (hash_l(mid))
    54             l = mid;
    55         else
    56             r = mid - 1;
    57     }
    58     return l;
    59 }
    } //左兄弟右儿子字符串字典树(二叉,省空间,时间换空间)
     1 const int N=1e6+10;
     2 int bit=8;
     3 int base=1<<bit;
     4 int mask=base-1;
     5 int maxbit=20;
     6 int n,x[N],h,next[N],m;
     7 int head[N],tial[N];
     8 void radixsort(int &h,int *x)
     9 {
    10     for (int i = 0; i < maxbit; i += bit)
    11     {
    12         memset(head, 0, sizeof(head[0]) * base);
    13         for (int j = h, tmp; j; j = tmp)
    14         //分桶
    15 
    16         {
    17             tmp = next[j];
    18             int c = (x[j] >> i) & mask;
    19             if (!head[c])
    20             {
    21                 head[c] = tial[c] = j;
    22                 next[j] = 0;
    23             }
    24             else
    25             {
    26                 next[tial[c]] = j;
    27                 next[j] = 0;
    28                 tial[c] = j;
    29             }
    30         }
    31         h = 0;
    32         int ti;
    33         //for(int j=0;j<base;j++) if(head[j]) //合并,升序
    34         for (int j = mask; j >= 0; j--)
    35             if (head[j]) //合并,降序
    36             {
    37                 if (!h)
    38                     h = head[j];
    39                 else
    40                     next[ti] = head[j];
    41                 ti = tial[j];
    42             }
    43     }
    44 }
    45 void init()
    46 {
    47     bit = 0;
    48     while (1 << bit < n)
    49         bit++;
    50     bit -= 3;
    51     bit = std::min(20, bit); //最大的比 maxbit小一点
    52     bit = std::max(4, bit);
    53     base = 1 << bit;
    54     mask = base - 1;
    55 }
    56 int main()
    57 {
    58     while (scanf("%d%d", &n, &m) == 2)
    59     {
    60         for (int i = 1; i <= n; i++)
    61         {
    62             scanf("%d", x + i);
    63             x[i] += 500000;
    64             next[i] = i + 1;
    65         }
    66         init();
    67         h = 1;
    68         next[n] = 0;
    69         radixsort(h, x);
    70 
    71         for (int i = h; i && m; i = next[i])
    72             printf("%d%c", x[i] - 500000, (--m) ? ' ' : '
    ');
    73         return 0;
    74     }
    75 }
    //多关键基数排序
     1 template <class T>
     2 void qsort(int l,int r,T *p)
     3 {
     4     if (l >= r)
     5         return;
     6     T t = p[l];
     7     int i = l, j = r;
     8     while (i < j)
     9     {
    10         //以第一个为基准排序,大的放左边,小的放右边
    11         while (i < j && p[j]->score <= t->score)
    12             j--; //找到一个小的
    13         p[i] = p[j];
    14         while (i < j && p[i]->score > t->score)
    15             i++; //找到一个大的
    16         p[j] = p[i];
    17     }
    18     p[i] = t;
    19     qsort(l, i - 1, p);
    20     qsort(i + 1, r, p);
    21 }
    //快排
     1 template<class T>
     2 void mergesort(int l,int r,T *p,T *tmp)
     3 {
     4     if (l == r)
     5         return;
     6     int mid = r - (r - l) / 2;
     7     mergesort(l, mid - 1, p, tmp);
     8     mergesort(mid, r, p, tmp);
     9     int i = l, j = mid, k = l;
    10     while (i < mid || j <= r)
    11     {
    12         //归并
    13         if (j > r || i < mid && p[i]->score >= p[j]->score)
    14             tmp[k++] = p[i++];
    15         else
    16             tmp[k++] = p[j++];
    17     }
    18     while (l <= r)
    19         p[l] = tmp[l++];
    20     //复制回原数组
    21 }
    //归并排序
     1 template <class T>
     2 void HeapAdjust(T *p,int s,int m)
     3 {
     4     T rc = p[s];
     5     //沿 key较大的孩子结点向下筛选
     6     for (int j = s << 1; j <= m; j <<= 1)
     7     {
     8         if (j < m && p[j] < p[j + 1])
     9             ++j;
    10         if (rc >= p[j])
    11             break;
    12         p[s] = p[j];
    13         s = j;
    14         //j为 key较大的记录的下标
    15         //rc应插入在位置 s上
    16     }
    17     p[s] = rc;
    18     //插入
    19 }
    20 template <class T>
    21 void HeapSort(T *p)
    22 {
    23     //数组下标从 1开始
    24     for (int i = n / 2; i > 0; --i)
    25         HeapAdjust(p, i, n); //建堆,不断将子二叉树调整为堆,然后整个二叉树就满足
    26     了堆性质
    27     for (int i = n, j = 1; j <= m; i--, j++)
    28     //每次将当前最大(小)(堆顶)元素,放到尾部,调整堆
    29     {
    30         swap(p[1], p[i]);
    31         HeapAdjust(p, 1, i - 1);
    32     }
    33 }
    //堆排序 //将某个子二叉树调整为堆,满足 p[i]>=k[i*2]&&p[i]>=k[i*2+1](或小于)
     1 template <class T>
     2 void HeapUpAdjust(T *p,int s)//从 s向上到 1调整堆
     3 {
     4     int x = p[s];
     5     while (s > 1)
     6     {
     7         if (x < p[s >> 1])
     8             p[s] = p[s >> 1];
     9         else
    10             break;
    11         s >>= 1;
    12     }
    13     p[s] = x;
    14 }
    15 template <class T>
    16 void HeapDownAdjust(T *p,int s,int n)//从 s向下到 n调整堆
    17 {
    18     int x = p[s];
    19     s <<= 1;
    20     while (s <= n)
    21     {
    22         if (s < n && p[s | 1] < p[s])
    23             s |= 1;
    24         if (p[s] >= x)
    25             break;
    26         p[s >> 1] = p[s];
    27 
    28         s <<= 1;
    29         p[s >> 1] = x;
    30     }
    31 }
    //堆调整

    优先队列入队:加元素到尾部,然后向上调整,size++
    优先队列出队:将最后一个元素放到顶部,向下调整堆,size--

     1 int n,a[N],d[N][20];
     2 void RMQ_init()
     3 {
     4     for (int i = 1; i <= n; i++)
     5         d[i][0] = a[i];
     6     for (int j = 1; (1 << j) <= n; j++)
     7         for (int i = 1; i + (1 << j) - 1 <= n; i++)
     8             d[i][j] = min(d[i][j - 1], d[i + (1 << (j - 1))][j - 1]);
     9 }
    10 int RMQ(int L,int R)
    11 {
    12     int k = 0;
    13     while ((1 << (k + 1)) <= R - L + 1)
    14         k++;
    15     return min(d[L][k], d[R - (1 << k) + 1][k]);
    16 }
    //RMQ
    公平游戏:一个游戏者可以把状态 A变成状态 B,另一个也可以.象棋是不公平游戏
    规则 1:一个状态是必败状态当且仅当它的所有后继都是必胜状态
    规则 2:一个状态是必胜状态当且仅当它至少有一个后继是必败状态
    dp时,对于每个状态,查找它的后继状态有没有必败状态,有就是必胜状态,没有就是必败状态
    当数据较大,dp打表会超时时就打出一个比较小的表找数(0出现)的规律
      1 struct Point
      2 {
      3     double x, y;
      4     Point(double x = 0, double y = 0) : x(x), y(y) {}
      5 };
      6 typedef Point Vector;
      7 Vector operator + (Vector A,Vector B) {
      8     return Vector(A.x + B.x, A.y + B.y); }
      9 Vector operator - (Point A,Point B) {
     10     return Vector(A.x - B.x, A.y - B.y); }
     11 Vector operator * (Vector A,double p) {
     12     return Vector(A.x * p, A.y * p); }
     13 Vector operator / (Vector A,double p) {
     14     return Vector(A.x / p, A.y / p); }
     15 bool operator < (const Point & a,const Point &b) {
     16     return a.x < b.x || (a.x == b.x && a.y < b.y); }
     17 const double eps=1e-9;
     18 const double pi=acos(-1);
     19 int dcmp(double x) {
     20     if (fabs(x) < eps)
     21         return 0;
     22     else
     23         return x < 0 ? -1 : 1; }
     24 bool operator == (const Point& a,const Point &b) {
     25     return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0; }
     26 
     27  
     28 //基本运算
     29 double Dot(Vector A,Vector B) //向量的点积
     30 {
     31     return A.x * B.x + A.y * B.y;
     32 }
     33 double Length(Vector A) //向量的长度
     34 {
     35     return sqrt(Dot(A, A));
     36 }
     37 double Angle(Vector A,Vector B) //两个向量的夹角
     38 {
     39     return acos(Dot(A, B) / Length(A) / Length(B));
     40 }
     41 double Cross(Vector A,Vector B) //向量叉积
     42 {
     43     return A.x * B.y - A.y * B.x;
     44 }
     45 double Area2(Point A,Point B,Point C)//三角形面积
     46 {
     47     return Cross(B - A, C - A);
     48 }
     49 Vector Rotate(Vector A,double rad)//向量逆时针旋转
     50 {
     51     return Vector(A.x * cos(rad) - A.y * sin(rad), A.x * sin(rad) + A.y * cos(rad));
     52 }
     53 Vector Normal(Vector A)
     54 {//计算向量的单位法向量(左转 90度以后把长度归一化),调用前确保 A不是 0向量
     55     double L = Length(A);
     56     return Vector(-A.y / L, A.x / L);
     57 }
     58 //点和直线
     59 Point GetLineIntersection(Point P,Vector v,Point Q,Vector w)
     60 {//调用前确保两条直线 P+tv和 Q+tw有唯一交点,即 Cross(v,w)非 0
     61     Vector u = P - Q;
     62     double t = Cross(w, u) / Cross(v, w);
     63     return P + v * t;
     64 }
     65 double DistanceToLine(Point P,Point A,Point B)
     66 {//点到直线的距离
     67     Vector v1 = B - A, v2 = P - A;
     68     return fabs(Cross(v1, v2)) / Length(v1); //不取绝对值得到有向距离
     69 }
     70 
     71  
     72 double DistanceToSegment(Point P,Point A,Point B)
     73 {//点到线段的距离
     74     if (A == B)
     75         return Length(P - A);
     76     Vector v1 = B - A, v2 = P - A, v3 = P - B;
     77     if (dcmp(Dot(v1, v2)) < 0)
     78         return Length(v2);
     79     else if (dcmp(Dot(v1, v3)) > 0)
     80         return Length(v3);
     81     else
     82         return fabs(Cross(v1, v2)) / Length(v1);
     83 }
     84 Point GetLineProjection(Point P,Point A,Point B)
     85 {//点在直线上的投影
     86     Vector v = B - A;
     87     return A + v * (Dot(v, P - A) / Dot(v, v));
     88 }
     89 bool SegmentProperIntersection(Point a1,Point a2,Point b1,Point b2)
     90 {//判线段相交,两线段恰好有一个公共点且不再任何一条线段的端点
     91     double c1 = Cross(a2 - a1, b1 - a1), c2 = Cross(a2 - a1, b2 - a1);
     92     double c3 = Cross(b2 - b1, a1 - b1), c4 = Cross(b2 - b1, a2 - b1);
     93     return dcmp(c1) * dcmp(c2) < 0 && dcmp(c3) * dcmp(c4) < 0;
     94 }
     95 bool PointOnSegment(Point p,Point a1,Point a2)
     96 {//判断点是否在线段上(不含端点,端点直接判 p和 a1或 a2是否相等)
     97     //if(p==a1||p==a2) return 1;//判点相同
     98     return dcmp(Cross(a1 - p, a2 - p)) == 0 && dcmp(Dot(a1 - p, a2 - p)) < 0;
     99 }
    100 //多边形
    101 double PolygonArea(Point *p,int n)
    102 {//多边形有向面积
    103     double area = 0;
    104     for (int i = 1; i < n - 1; i++)
    105         area += Cross(p[i] - p[0], p[i + 1] - p[0]);
    106     return area / 2;
    107 }
    108 int isPointInPolygon(Point p,Point*poly,int n)
    109 {//点在多边形判定
    110     int wn = 0;
    111     for (int i = 0; i < n; i++)
    112     {
    113         if (PointOnSegment(p, poly[i], poly[(i + 1) % n]))
    114             return -1; //在边界上
    115         int k = dcmp(Cross(poly[(i + 1) % n] - poly[i], p - poly[i]));
    116         int d1 = dcmp(poly[i].y - p.y);
    117         int d2 = dcmp(poly[(i + 1) % n].y - p.y);
    118         if (k > 0 && d1 <= 0 && d2 > 0)
    119             wn++;
    120         if (k < 0 && d2 <= 0 && d1 > 0)
    121             wn--;
    122     }
    123     if (wn != 0)
    124         return 1; //内部
    125     return 0;
    126     //外部
    127 }
    128 
    129  
    130 //计算凸包,输入点数组 p,个数为 p,输出点数组 ch.函数返回凸包顶点数
    131 //输入不能有重复点.注意:函数执行完之后输入点的顺序被破坏
    132 //如果不希望在凸包的边上有输入点,把两个<=改成<
    133 //在精度要求高时建议用 dcmp比较
    134 int ConvexHull(Point* p,int n,Point *ch)
    135 {
    136     sort(p, p + n);
    137     int m = 0;
    138     for (int i = 0; i < n; i++)
    139     {
    140         while (m > 1 && Cross(ch[m - 1] - ch[m - 2], p[i] - ch[m - 2]) <= 0)
    141             m--;
    142         ch[m++] = p[i];
    143     }
    144     int k = m;
    145     for (int i = n - 2; i >= 0; i--)
    146     {
    147         while (m > k && Cross(ch[m - 1] - ch[m - 2], p[i] - ch[m - 2]) <= 0)
    148             m--;
    149         ch[m++] = p[i];
    150     }
    151     if (n > 1)
    152         m--;
    153     return m; //凸包顶点数
    154 }
    155 double PointoRecDist(Point p,Point ra,Point rb)
    156 {//点到长方形的距离
    157     if (ra.x > rb.x)
    158         swap(ra.x, rb.x); //变成左上和右下角
    159     if (ra.y > rb.y)
    160         swap(ra.y, rb.y);
    161     double dx = 0, dy = 0;
    162     if (p.x < ra.x)
    163         dx = ra.x - p.x;
    164     else if (p.x > rb.x)
    165         dx = p.x - rb.x;
    166     if (p.y < ra.y)
    167         dy = ra.y - p.y;
    168     else if (p.y > rb.y)
    169         dy = p.y - rb.y;
    170     return sqrt(dx * dx + dy * dy);
    171 }
    172 double getcycy(double x,double neg,Point cyc,double ri)
    173 {//由 x得到圆上点的 y坐标,neg表示上 1下-1
    174     return cyc.y + neg * sqrt(ri * ri - (x - cyc.x) * (x - cyc.x));
    175 }
    //几何模板
     1 const double eps=1e-9;
     2 int gauss(double a[N][N],bool *l,double *ans,int n)
     3 {
     4     int res = 0, r = 0;
     5     for (int i = 0; i < n; i++)
     6         l[i] = false; //全部初始化为自由元
     7     for (int i = 0; i < n; i++)
     8     {
     9         for (int j = r; j < n; j++)
    10             if (fabs(a[j][i] > eps))
    11             {
    12                 for (int k = i; k <= n; k++)
    13                     swap(a[j][k], a[r][k]);
    14                 break;
    15             }
    16         if (fabs(a[r][i]) < eps)
    17         {
    18             res++;
    19             continue;
    20         }
    21         for (int j = 0; j < n; j++)
    22             if (j != r && fabs(a[j][i]) > eps)
    23             {
    24                 double tmp = a[j][i] / a[r][i];
    25                 for (int k = i; k <= n; k++)
    26                     a[j][k] -= tmp * a[r][k];
    27             }
    28         l[i] = true;
    29         r++;
    30     }
    31     for (int i = 0; i < n; i++)
    32         if (l[i])
    33             for (int j = 0; j < n; j++)
    34                 if (fabs(a[j][i]) > 0)
    35                     ans[i] = a[j][n] / a[j][i];
    36     return res;
    37 }
    //gauss消元模板,返回矩阵的秩,l数组标记自由元,ans为结果,n为未知数个数
     1 //若只是记录某个数是否存在可用 bitset优化,原来已存在的数记为 bitset x ;
     2 //则 x中所有标记位为 1的数+a[i]之后变成 x=x<<a[i]|x
     3 //如果数最大小于 64可用 long long代替 bitset,更快,最大小于 128时用__int128
     4 //无限背包有排列种数
     5 //(1,4,9,...,17^2 中可重复选能有多少种方法拼成 1~300,114,141,411,111111 4种拼成 6的方法)
     6 memset(dp,0,sizeof(dp));
     7 dp[0]=1;
     8 for(int i=0;i<=300;i++) //每个数都可以往后面加 1,4,...,17^2
     9 for(int j=1;j*j+i<=300;j++)
    10 dp[j*j+i]+=dp[i];//取多少个 i
    11 //无限背包组合种数
    12 //(1,4,9,...,17^2 中可重复选能有多少种方法拼成 1~300,114,111111 2种拼成 6的方法)
    13 memset(dp,0,sizeof(dp));
    14 dp[0]=1;
    15 for(int i=1;i*i<=300;i++)//取的数递增,即取了 1后只能取 4再 9再...,不能继续取 1了
    16 for(int j=0;j+i*i<=300;j++)
    17 dp[j+i*i]+=dp[j];
    18 将 n拆分为 m个数(n个相同的球放入 m个盒子)的组合方法数<=>将 n拆分为最大数为 m相加的组合方法数
    19 推论: 设 m<=n,n拆分成最多 m个数的和的拆分数等于将 n拆分成最大数不超过 m的拆分数
    无限背包计数
      1 #include <bits/stdc++.h>
      2 typedef long long LL;
      3 const int N=1e6+10;
      4 int cas=1,T;
      5 int m,n;
      6 char s[40][40];
      7 LL dp[2][N];
      8 const int HASH=30007;
      9 int head[HASH],next[N],state[2][N],hn[2];
     10 inline int insert(int s,int *state,LL *dp)
     11 {
     12     int h = state[s] * 7 % HASH; //必要时乘个质数会散一些,如果还有一个数要变成(state[s]+x*1007)%HASH
     13     int u = head[h];
     14     while (u)
     15     {
     16         if (state[u] == state[s])
     17         {
     18             dp[u] += dp[s];
     19             return 0;
     20         }
     21         u = next[u];
     22     }
     23     next[s] = head[h];
     24     head[h] = s;
     25     return 1;
     26 }
     27 inline void ha(int x,int k,int d,int &h)
     28 {
     29     state[d ^ 1][h] = x;
     30     dp[d ^ 1][h] = dp[d][k];
     31     h += insert(h, state[d ^ 1], dp[d ^ 1]);
     32 }
     33 LL ans[40][40];
     34 int main()
     35 {
     36     while (scanf("%d%d", &n, &m) == 2)
     37     {
     38         for (int i = 0; i < n; i++)
     39             scanf("%s", s[i]);
     40         for (int i = 0; i < n; i++)
     41             for (int j = 0; j < m; j++)
     42                 s[i][j] = (s[i][j] == '.');
     43         int d = 0;
     44         int M = m << 1;
     45         memset(ans, 0, sizeof(ans));
     46         state[0][1] = 0;
     47         dp[0][1] = 1;
     48         hn[0] = 2;
     49         for (int i = 0; i < n; i++)
     50         {
     51 
     52             for (int j = 0; j < m; j++, d ^= 1)
     53             {
     54                 hn[d ^ 1] = 1;
     55                 if (!s[i][j]) //障碍
     56                 {
     57                     for (int k = 1, &h = hn[d ^ 1]; k < hn[d]; k++)
     58                     {
     59                         int t = state[d][k];
     60                         if ((t & (3 << M)) || (t & 3))
     61                             continue;
     62                         state[d ^ 1][h] = t << 2;
     63                         dp[d ^ 1][h] = dp[d][k];
     64                         h++;
     65                     }
     66                     continue;
     67                 }
     68                 memset(head, 0, sizeof(head));
     69                 for (int k = 1, &h = hn[d ^ 1]; k < hn[d]; k++) //每个非障碍格子都可以走
     70                 {
     71                     int t = state[d][k];
     72                     if ((t & (3 << M)) && (t & 3))
     73                     {
     74                         int x = t & 3;
     75                         int y = t & (3 << M);
     76                         t = t ^ x ^ y;
     77                         y >>= M;
     78                         if (x == 1 && y == 2)
     79                         {
     80                             if (t == 0)                //没有没有其它插头时可以是一条(i,j)结束的回路
     81                                 ans[i][j] += dp[d][k]; //()
     82                         }
     83                         else if (x == 2 && y == 1)
     84                             ha(t << 2, k, d, h);   //)(
     85                         else if (x == 2 && y == 2) //))
     86                         {
     87                             for (int l = 2, c = 0; l < M; l += 2) //往前找到匹配的(并改为)
     88                             {
     89                                 if (((t >> l) & 3) == 2)
     90                                     c--;
     91                                 else if (((t >> l) & 3) == 1)
     92                                     c++;
     93                                 if (c == 1)
     94                                 {
     95                                     t = t ^ (3 << l);
     96                                     break;
     97                                 }
     98                             }
     99                             ha(t << 2, k, d, h);
    100                         }
    101                         else
    102                         {
    103                             //((
    104                             for (int l = M - 2, c = 0; l > 0; l -= 2) //往后找到匹配的)并改为(
    105                             {
    106                                 if (((t >> l) & 3) == 1)
    107                                     c--;
    108 
    109                                 else if (((t >> l) & 3) == 2)
    110                                     c++;
    111                                 if (c == 1)
    112                                 {
    113                                     t = t ^ (3 << l);
    114                                     break;
    115                                 }
    116                             }
    117                             ha(t << 2, k, d, h);
    118                         }
    119                     }
    120                     else if (!(t & (3 << M)) && !(t & 3)) //##
    121                     {
    122                         //if(s[i][j]) ha(t<<2,k,d,h);//不走
    123                         if (i + 1 < n && s[i + 1][j] && j + 1 < m && s[i][j + 1])
    124                             ha(t << 2 | 6, k, d, h);
    125                     }
    126                     else
    127                     {
    128                         //#( #) (# )#
    129                         int x = t & 3;
    130                         int y = t & (3 << M);
    131                         if (x)
    132                             t ^= x;
    133                         else if (y)
    134                             t ^= y, x = y >> M;
    135                         if (i + 1 < n && s[i + 1][j])
    136                             ha(t << 2 | (x << 2), k, d, h);
    137                         if (j + 1 < m && s[i][j + 1])
    138                             ha(t << 2 | x, k, d, h);
    139                     }
    140                 }
    141             }
    142         }
    143         for (int i = n - 1; i >= 0; i--)
    144         {
    145             for (int j = m - 1; j >= 0; j--)
    146                 if (s[i][j])
    147                 {
    148                     printf("%lld
    ", ans[i][j]);
    149                     i = -1;
    150                     break;
    151                 }
    152         }
    153     }
    154     return 0;
    155 }
    //轮廓线 dp求只有一个闭合回路方法数(括号匹配判断是否形成回路)
     1 int n,a[N],idx[N];
     2 int lbig[N],lsmall[N],rsmall[N],rbig[N],bit[N],id[N];
     3 //lbig左边比当前数大,rbig右边比当前数大(不等于)
     4 LL sum(int x)
     5 {
     6     LL rec = 0;
     7     while (x)
     8     {
     9         rec += bit[x];
    10         x -= x & -x;
    11     }
    12     return rec;
    13 }
    14 LL add(int x)
    15 {
    16     while (x <= n)
    17     {
    18         bit[x]++;
    19         x += x & -x;
    20     }
    21 }
    22 void cal()
    23 {
    24     for (int i = 1; i <= n; i++)
    25         idx[i] = a[i];
    26     sort(idx + 1, idx + n + 1);
    27     memset(bit, 0, sizeof(bit));
    28     map<int, int> mp; //用于处理相同数
    29     for (int i = 1; i <= n; i++)
    30     {
    31         id[i] = lower_bound(idx + 1, idx + 1 + n, a[i]) - idx;
    32         lsmall[i] = sum(id[i] - 1);
    33         add(id[i]);
    34         int &x = mp[a[i]];
    35         lbig[i] = i - 1 - lsmall[i] - x;
    36         x++;
    37     }
    38     memset(bit, 0, sizeof(bit));
    39     mp.clear();
    40     for (int i = n; i > 0; i--)
    41     {
    42         rsmall[i] = sum(id[i] - 1);
    43         add(id[i]);
    44         int &x = mp[a[i]];
    45         rbig[i] = n - i - rsmall[i] - x;
    46         x++;
    47     }
    48 }
    //BIT统计逆序对
     1 LL count(LL n,LL num)
     2 {
     3     LL e = 1, ans = 0;
     4     for (int i = 0; n >= e; e *= 10, i++)
     5     {
     6         LL pre = n / e / 10;
     7         LL dig = n / e % 10;
     8         LL suf = n % e;
     9         if (dig > num)
    10             pre++;
    11         if (!num)
    12             pre--; //num==0时去掉前导 0的情况
    13         ans += pre * e;
    14         if (dig == num)
    15             ans += suf;
    16     }
    17     if (n && !num)
    18         ans++; //num==0且 n>0时 0也要算上
    19     return ans;
    20 }
    //数位 dp,数 1~n-1中的数位总共出现了多少个 num(0<=num<=9)
      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 typedef long long LL;
      4 const int N=1e5+10;
      5 const int INF=0x3f3f3f3f;
      6 const int bit=7;
      7 int cas=1,T;
      8 int dp[10][3];
      9 void init()
     10 {
     11     memset(dp, 0, sizeof(dp));
     12     dp[0][2] = 1;
     13     for (int i = 1; i <= bit; i++)
     14     {
     15         dp[i][0] = dp[i - 1][0] * 10 + 2 * dp[i - 1][1] + dp[i - 1][2]; //62,4
     16         dp[i][1] = dp[i - 1][1] + dp[i - 1][2];                         //no62,4 head=2
     17         dp[i][2] = 7 * dp[i - 1][1] + 8 * dp[i - 1][2];                 //no62,4 head!=2
     18     }
     19     //for(int i=1;i<=bit;i++) printf("%d %d %d %d
    ",i,dp[i][0],dp[i][1],dp[i][2]);
     20 }
     21 int count(int n)
     22 {
     23     int ans = 0;
     24     for (int i = bit, e = 1e6 + 0.5; i >= 0; i--, e /= 10)
     25     {
     26         if (e > n)
     27             continue;
     28         int pre = n / e % 10;  //当前位数字
     29         ans += pre * dp[i][0]; //0~pre-1 *e
     30         if (pre > 6 || pre == 6 && n * 10 / e % 10 > 2)
     31             ans += dp[i][1];
     32         //6+ no62,4 head=2
     33         当前位 > 6 或者 当前位 = 6且下一位 > 2
     34 
     35                                  if (pre > 4) ans += dp[i][2] + dp[i][1]; //4+ no62,4 head=2 + no62,4, head!=2
     36         if (pre == 4 || n / e % 100 == 62)                                //+ 后边所有
     37         {
     38             ans += n % e;
     39             break;
     40         }
     41     }
     42     return ans;
     43 }
     44 int main()
     45 {
     46     init();
     47     int l, r;
     48     //while(scanf("%d%d",&l,&r)==2 && (l&&r)) printf("%d %d
    ",count(r+1),count(l));
     49     while (scanf("%d%d", &l, &r) == 2 && (l && r))
     50         printf("%d
    ", r - l + 1 - count(r + 1) + count(l));
     51     return 0;
     52 }
     53 //数位 dp记忆化搜索,从高位往低位搜
     54 //这里是[l,r]中数位中连续奇数数字有偶数个,连续偶数数字有奇数个
     55 //第三维表示数位的数字,还没有数字为 2,奇数为 1,偶数为 0
     56 //第四维表示数位的连续个数,还没有数字为 2,奇数个为 1,偶数个为 0
     57 //第二维表示当前数位为 dig时有多少种
     58 #include <bits/stdc++.h>
     59 using namespace std;
     60 typedef long long LL;
     61 const int N=1e5+10;
     62 const int INF=0x3f3f3f3f;
     63 int cas=1,T;
     64 LL dp[20][10][3][3];//dp[a][b][c][d]记忆化前面数位为 d个 c,当前位为 b,后面有 a个 9时的种数
     65 LL dfs(int n,LL e,LL x,int odd,int even)
     66 {
     67     if (n < 0)
     68         return odd != even;
     69     if (e > x && odd == 2)
     70         return dfs(n - 1, e / 10, x, odd, even);
     71     int dig = x / e % 10;
     72     if ((x + 1) % e == 0 && dp[n][dig][odd][even] != -1)
     73         return dp[n][dig][odd][even]; //如果已经搜过直
     74     接返回
     75     if (odd == 2)
     76     {
     77         //还没有数位时不同转移
     78         LL ans = 0;
     79         ans += dfs(n - 1, e / 10, e - 1, 2, 2); //前导 0,还是没有数位
     80         for (int i = 1; i < dig; i++)
     81             ans += dfs(n - 1, e / 10, (i + 1) * e - 1, i & 1, 1);
     82         ans += dfs(n - 1, e / 10, x % e, dig & 1, 1);
     83         if ((x + 1) % e == 0)
     84             dp[n][dig][odd][even] = ans;
     85         return ans;
     86     }
     87     LL ans = 0;
     88     for (int i = 0; i < dig; i++)
     89         if ((i & 1) == odd || (i & 1) != odd && odd != even)
     90             ans += dfs(n - 1, e / 10, (i + 1) * e - 1, i & 1, ((i & 1) == odd) ? (even ^ 1) : 1);
     91 
     92     if ((dig & 1) == odd || (dig & 1) != odd && odd != even)
     93         ans += dfs(n - 1, e / 10, x % e, dig & 1, ((dig & 1) == odd) ? (even ^ 1) : 1);
     94     if ((x + 1) / 10 == e)
     95         dp[n][dig][odd][even] = ans; //x=a99…99 时记忆化
     96     return ans;
     97 }
     98 int main()
     99 {
    100     memset(dp, -1, sizeof(dp));
    101     scanf("%d", &T);
    102     while (T--)
    103     {
    104         LL l, r;
    105         scanf("%lld%lld", &l, &r);
    106         LL lans = dfs(18, 1e18, l - 1, 2, 2);
    107         //printf("lans:%lld
    ",lans);
    108         LL rans = dfs(18, 1e18, r, 2, 2);
    109         //printf("rans:%lld
    ",rans);
    110         printf("Case #%d: %lld
    ", cas++, rans - lans);
    111     }
    112     return 0;
    113 }
    //数位 dp模板(递推过程),考虑前导 0是注意 0~9999…9999 这种的处理 //这里是算[l,r]中没有 62也没有 4的个数,从低位往高位推,每次在最高位加一个数字进行转移
    TSP问题:有 n个城市,两两之间均有道路相连,距离为 dis(i,j),求最短的路径经过每个点一次并回到原点
    做法:状压 dp,O(n*2^n)
    如果给定起点和终点 s,e,则可以用 O(n^2)dp 解决,每次在当前最小路径中插入下一个点获得加一个点进来后的最
    小路径
    //圆周涂色
    把一个圆分成 n个扇形,每个扇形可以涂 m种颜色,要求相邻的颜色互不相同,有多少种涂法?
    把 n个扇形的涂法记为 f(n),则 f(n)+f(n-1)=m*(m-1)^(n-1),包含第一个和第 n个扇形涂色相同的情况,相当于
    将第 1个扇形和第 n个扇形合并成一个扇形的涂法,化简得 f(n)=(m-1)^n+(n&1?-1:1)*(m-1);
     1 const int M=75;
     2 int
     3 ro[3][M]={{0,10,11,12,13,14,15,16,17,18,46,47,48,49,50,51,52,53,54,25,22,19,26,23,20,27,24,
     4 21,9,8,7,6,5,4,3,2,1,39,42,45,38,41,44,37,40,43,36,35,34,33,32,31,30,29,28,//3*3*6=54个方格
     5 63,59,55,62,64,56,58,66,65,60,57,61,
     6 //十二条边
     7 71,72,68,67,74,73,69,70},//8个顶点
     8 {0,43,40,37,44,41,38,45,42,39,16,13,10,17,14,11,18,15,12,7,4,1,8,5,2,9,6,3,30,33,36,29,32,3
     9 5,28,31,34,52,49,46,53,50,47,54,51,48,25,22,19,26,23,20,27,24,21,
    10 62,58,61,66,55,57,65,63,59,56,60,64,
    11 71,67,70,74,72,68,69,73},
    12 {0,7,4,1,8,5,2,9,6,3,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,4
    13 2,43,44,45,10,11,12,13,14,15,16,17,18,48,51,54,47,50,53,46,49,52,
    14 56,57,58,55,60,61,62,59,64,65,66,63,
    15 68,69,70,67,72,73,74,71}};
    16 
    17  
    18 int pu[M],t[M],pemu[100][M],pn;
    19 void count(int *v)
    20 {
    21     int vis[M];
    22     memset(vis, 0, sizeof(vis));
    23     for (int i = 1; i < M; i++)
    24         if (!vis[i])
    25         {
    26             int c = 0;
    27             int u = i;
    28             while (!vis[u])
    29             {
    30                 vis[u] = 1;
    31                 u = pu[u];
    32                 c++;
    33             }
    34             v[c]++;
    35         }
    36 }
    37 void init()
    38 {
    39     memset(pemu, 0, sizeof(pemu));
    40     pn = 0;
    41     set<LL> s;
    42     map<int, int> cc;
    43     for (int i = 0; i < M; i++)
    44         pu[i] = i;
    45     for (int i = 1; i <= 4; i++)
    46     {
    47         for (int l = 1; l < M; l++)
    48             t[l] = pu[ro[0][l]];
    49         memcpy(pu, t, sizeof(pu));
    50         for (int j = 1; j <= 4; j++)
    51         {
    52             for (int l = 1; l < M; l++)
    53                 t[l] = pu[ro[1][l]];
    54             memcpy(pu, t, sizeof(pu));
    55             for (int k = 1; k <= 4; k++)
    56             {
    57                 for (int l = 1; l < M; l++)
    58                     t[l] = pu[ro[2][l]];
    59                 memcpy(pu, t, sizeof(pu));
    60                 //printf("i:%d j:%d k:%d
    ",i,j,k);
    61                 LL ha = 0;
    62                 for (int l = 1; l < M; l++)
    63                     ha = ha * 1000007 + pu[l];
    64                 //for(int l=1;l<=12;l++) printf("%d ",pu[l]);printf("
    ");
    65                 if (s.count(ha))
    66                     continue;
    67                 s.insert(ha);
    68                 count(pemu[pn]);
    69                 int sum = 0;
    70                 for (int l = 1; l < M; l++)
    71                     printf("%d ", pemu[pn][l]), sum += pemu[pn][l];
    72                 printf("
    ");
    73                 cc[sum]++;
    74                 pn++;
    75             }
    76         }
    77     }
    78     for (map<int, int>::iterator it = cc.begin(); it != cc.end(); it++)
    79         printf("%d %d
    ", it->first, it->second);
    80     printf("%d
    ", s.size());
    81 }
    //置换打表
     1 //f(n)=a*x^n+b*x^n,得到 f(n)=c1*f(n-1)+c2*f(n-2),a*x^n=f(n)-b*x^n
     2 //求 a^n%mod用矩阵快速幂求解 f(n)时 f(n)%mod的循环节为(mod*mod-1),最小循环节是(mod*mod-1)的约数
     3 //即 f(n)%mod=f(n%(mod*mod-1))%mod
     4 //当循环节为 p时 f(0)==f(p) && f(1)==f(p+1)
     5 //可以暴力找循环节
     6 const int M=2;
     7 struct mar
     8 {
     9     LL a[M][M];
    10     mar operator*(const mar &b)
    11     {
    12         mar ans;
    13         memset(&ans, 0, sizeof(ans));
    14         for (int i = 0; i < M; i++)
    15             for (int j = 0; j < M; j++)
    16                 for (int k = 0; k < M; k++)
    17                     ans.a[i][j] = (ans.a[i][j] + a[i][k] * b.a[k][j]) % mod;
    18         return ans;
    19     }
    20 };
    21 LL a[M]={2,1};//递推式 f(n)=a[0]f(n-1)+a[1]f(n-2)+...+a[M-1]f(n-M)
    22 LL f[M]={1,0};//f[0]=f(M-1),f[1]=f(M-2),...,f(M-2)=f(1),f(M-1)=f(0) 倒过来的
    23 LL mar_pow(LL n)
    24 {
    25     mar ans, t;
    26     memset(&ans, 0, sizeof(ans));
    27     memset(&t, 0, sizeof(t));
    28     for (int i = 0; i < M; i++)
    29         ans.a[i][i] = 1; //单位矩阵,相当于快速幂中初始化为 1
    30     memcpy(t.a[0], a, sizeof(a));
    31     for (int i = 1; i < M; i++)
    32         t.a[i][i - 1] = 1;
    33     while (n)
    34     {
    35         if (n & 1)
    36             ans = ans * t;
    37         t = t * t;
    38         n >>= 1;
    39     }
    40     LL res = 0;
    41     for (int i = 0; i < M; i++)
    42         res = (res + ans.a[M - 1][i] * f[i]) % mod;
    43     //f(n)=f(n-1)*ans.a[M-1][i]+...+f(0)*ans.a[M-1][0];
    44     return res;
    45 }
    //通用矩阵快速幂
     1 void dfs(int x)
     2 {
     3     int pos = upper_bound(b + 1, b + 1 + n, k / a[x]) - b - 1;
     4     ans -= sum(pos);
     5     for (int i = 0; i < u[x].size(); i++)
     6         dfs(u[x][i]);
     7     ans += sum(pos);
     8     add(upper_bound(b + 1, b + 1 + n, a[x]) - b - 1);
     9 }
    10 struct node
    11 {
    12     int i, x, pos;
    13 };
    14 void slove(int x)//由上面的 dfs改成的手写栈
    15 {
    16     stack<node> s;
    17     int pos = upper_bound(b + 1, b + 1 + n, k / a[x]) - b - 1;
    18     s.push(node{0, x, pos});
    19     while (!s.empty())
    20     {
    21         node v = s.top();
    22         s.pop();
    23         if (v.i == u[v.x].size()) //dfs结束时
    24         {
    25             ans += sum(v.pos);
    26             add(upper_bound(b + 1, b + 1 + n, a[v.x]) - b - 1);
    27             continue; //return
    28         }
    29         x = u[v.x][v.i++]; //子树
    30         s.push(v);
    31         pos = upper_bound(b + 1, b + 1 + n, k / a[x]) - b - 1;
    32         ans -= sum(pos);
    33         s.push(node{0, x, pos}); //子树节点入栈
    34     }
    35 }
    //dfs改手写栈
    求<=n中除 p外所有质数的乘积%p
    要解决这个问题首先要理解一个动态规划的定义,定义 S(v,p)为 1−v 中经过小于等于 p 的素数筛过之后的数的个数,
    即此时整个数集里只包含<=p 的素数以及素因子>p 的数。
    相应的有状态转移 S(v,p)=S(v,p−1)–(S(v/p,p−1)−S(p−1,p−1))
    相应的可以定义状态 F(v,p)为 1−v 中经过小于等于 p 的素数筛过之后的数的乘积。相应的转移方程为:
    F(v,p)=F(v,p−1)/(F(v/p,p−1)/F(p−1,p−1)∗pS(v/p,p−1)−S(p−1,p−1))
    原题中要模的是 M,所以在定义 S(v,p)和相应的 F(v,p)时应当改为 1−v 中(除了 M,2M…)经过小于等于 p 的素数筛过
    之后的数的个数,以及这些数的乘积,这个实际上影响到的是初始化的阶段。
    实现上由于 v 的取值只需要用到 n/1,n/2…的值,所以分别用 l,h 的两种数组记录,其中 cl[x]表示的 S(x,p),ch[x]表示
    S(n/x,p),pl[x]表示 F(x,p),ph[x]表示 F(n/x,p)。
     1 syntax on
     2 "高亮
     3 set nu
     4 "显示行号
     5 set softtabstop=4
     6 set shiftwidth=4
     7 set smartindent
     8 set scrolloff=7
     9 set mouse=a
    10 "按 tab缩进 4个空格大小
    11 "默认缩进 4个空格大小(indent的缩进)
    12 "自动缩进
    13 "光标移动到 buffer的顶部和底部时保持 7行距离
    14 "鼠标所有功能可用
    15 set cursorline
    16 "当前行下划线划出
    17 "出现 swap文件时用这个
    18 set nobackup
    19 set noswapfile
    20 winpos -4 -4
    21 "设置窗口位置,使用 vim时自动最大化窗口
    22 set lines=50 columns=200 "设定窗口大小 "按 F5编译运行
    23 set guifont=UbuntuMono 14
    24 colorscheme desert
    25 "Ubuntu下 GVIM设置英文字体,字体名和字体大小
    26 "F5编译运行
    27 "w保存文本 ! g++ % -o %< 编译代码 ! ./%< linux执行 ! %<.exe windows执行
    28 map <F5> :call Compile()<CR>
    29 func Compile()
    30 :w
    31 :! g++ -std=c++11 % -o %<
    32 :! ./%<
    33 endfunc
    34 "noremap insert模式(打字时的模式)下映射
    35 "vmap/vnoremap visaul模式(选择时的模式)下映射
    36 "map/nnoremap normal模式(按下 Esc后的模式)下映射
    37 map <C-a> ggVG
    38 vmap <C-c> "+y
    39 map <C-v> "+p
    40 map zz I//<Esc>
    41 "Ctrl+a全选
    42 "Ctrl+c选择后复制,可粘贴到外编辑器,如果只在 vim中粘贴按 y复制即可
    43 "Ctrl+v normal模式下粘贴外部复制的文本
    44 "zz行首注释
    45 map tt I<Right><Right><Backspace><Backspace><Esc> "tt取消注释
    46 "cpp文件自动输出,F2手动输出
    47 auto BufNewFile *.cpp exec ":call Preset()"
    48 map<F2> :call Preset()<CR>
    49 func Preset()
    50 "setline将当前行设为字符串,append在当前行后追加
    51 call setline(line("."),"#include <bits/stdc++.h>")
    52 let l=line(".")-1
    53 let l=l+1 | call append(l,"using namespace std;")
    54 let l=l+1 | call append(l,"typedef long long LL;")
    55 let l=l+1 | call append(l,"const int N=1e5+10;")
    56 let l=l+1 | call append(l,"const int INF=0x3f3f3f3f;")
    57 
    58  
    59 let l=l+1 | call append(l,"const int mod=1e9+7;")
    60 let l=l+1 | call append(l,"int cas=1,T;")
    61 let l=l+1 | call append(l,"int main()")
    62 let l=l+1 | call append(l,"{")
    63 let l=l+1 | call append(l," //freopen("in","r",stdin);")
    64 let l=l+1 | call append(l," //scanf("%d",&T);")
    65 let l=l+1 | call append(l," return 0;")
    66 let l=l+1 | call append(l,"}")
    67 endfunc
    68 """""""""""下面的不需要用到就不要打了
    69 "F3输出头文件,bits/stdc++.h可用时不需要
    70 map <F3> :call AddHeader()<CR>
    71 func! AddHeader()
    72 call setline(line("."),"#include <cstdio>")
    73 let l=line(".")-1
    74 let l=l+1 | call append(l,"#include <queue>")
    75 let l=l+1 | call append(l,"#include <cstring>")
    76 let l=l+1 | call append(l,"#include <string>")
    77 let l=l+1 | call append(l,"#include <iostream>")
    78 let l=l+1 | call append(l,"#include <cstdlib>")
    79 let l=l+1 | call append(l,"#include <algorithm>")
    80 let l=l+1 | call append(l,"#include <vector>")
    81 let l=l+1 | call append(l,"#include <map>")
    82 let l=l+1 | call append(l,"#include <set>")
    83 let l=l+1 | call append(l,"#include <ctime>")
    84 let l=l+1 | call append(l,"#include <cmath>")
    85 let l=l+1 | call append(l,"#include <cctype>")
    86 endfunc
    87 "set guifont=Consolas:h14:cANSI
    88 "windows下设置英文字体,字体名和字体大小
    "Vim配置,引号开头的是注释,不用打
     1 1)、单点增减+区间求和
     2 思路:C[x]表示该点的元素:sum(x)=C[1]+C[2]+……C[x]
     3 int arr[MAXN];
     4 inline int sum(int x){
     5     int res = 0;
     6     while (x)
     7         res += arr[x], x -= lowbit(x);
     8     return res;}
     9 inline void add(int x,int n){
    10     while (x < MAXN)
    11         arr[x] += n, x += lowbit(x);}
    12 inline int query(int x,int y){
    13     return sum(y) - sum(x - 1);}
    142)、区间增减+单点查询
    15 思路:C[x]表示该点元素与左边元素的差值:num[x]=C[1]+C[2]+……C[x]
    16 int arr[MAXN]
    17 inline int sum(int x){
    18     int res = 0;
    19     while (x)
    20         res += arr[x], x -= lowbit(x);
    21     return res;}
    22 inline void add(int x,int n){
    23     while (x < MAXN)
    24         arr[x] += n, x += lowbit(x);}
    25 inline int update(int x,int y,int n){
    26     add(x, n);
    27     add(y + 1, -n);}
    283)、区间增减+区间查询
    29 思路:C1[x]表示该点元素与左边的差值,C2[x]表示的是 x*C[x]
    30 sum(sum(C[j],j<=i)i<=x)
    31 = x*C[1]+(x-1)*C[2]+……+C[x]
    32 =(x+1)*sum(C[i],i<=x)-sum(i*C[i],i<=x);
    33 则可以想到用 C1[x]维护 C[x]的值,C2[x]维护 x*C[X]的值
    34 template <typename X>
    35 struct tree_array{
    36     struct tree_array_single
    37     {
    38         X arr[MAXN];
    39 
    40         void add(int x, X n)
    41         {
    42             while (x <= N)
    43                 arr[x] += n, x += lowbit(x);
    44         }
    45         X sum(int x)
    46         {
    47             X sum = 0;
    48             while (x)
    49                 sum += arr[x], x -= lowbit(x);
    50             return sum;
    51         }
    52     } T1, T2;
    53     void reset()
    54     {
    55         CLR(T1.arr, 0);
    56         CLR(T2.arr, 0);
    57     }
    58     void add(int x, X n)
    59     {
    60         T1.add(x, n);
    61         T2.add(x, x * n);
    62     }
    63     void update(int L, int R, int n)
    64     {
    65         add(L, n);
    66         add(R + 1, -n);
    67     }
    68     X sum(int x) { return (x + 1) * T1.sum(x) - T2.sum(x); }
    69     X query(int L, int R) { return sum(R) - sum(L - 1); }
    70 };
    14、树状数组
      1 ①单点增减(add) + 矩形求和(query)
      2 ②矩形增减(update) + 单点求值(sum)
      3 int arr[MAXN][MAXN]
      4 inline void add(int x,int y,int n) {
      5     for (int i = x; i < MAXN; i += lowbit(i))
      6         for (int j = y; j < MAXN; j += lowbit(j))
      7             arr[i][j] += n;
      8 }
      9 inline int sum(int x,int y){
     10     int res = 0;
     11     for (int i = x; i; i -= lowbit(i))
     12         for (int j = y; j; j -= lowbit(j))
     13             res += arr[i][j];
     14     return res;
     15 }
     16 inline int query(int L,int B,int R,int T) {
     17     return sum(R, T) + sum(L - 1, B - 1) - sum(R, B - 1) - sum(L - 1, T);
     18 }
     19 inline void update(int L,int B,int R,int T,int n){
     20     update(L, B, n);
     21     update(L, T + 1, n);
     22     update(R + 1, B, n);
     23     update(R + 1, T + 1, n);
     24 }
     25 ③矩形增减(update)+ 矩形求和(query)
     26 template<typename X>
     27 class tree_array{
     28     struct tree_array_single
     29     {
     30         X arr[MAXN][MAXN];
     31         void add(int x, int y, X n)
     32         {
     33             for (int i = x; i < MAXN; i += lowbit(i))
     34                 for (int j = y; j < MAXN; j += lowbit(j))
     35                     arr[i][j] += n;
     36         }
     37         X sum(int x, int y)
     38         {
     39             X res = 0;
     40             for (int i = x; i; i -= lowbit(i))
     41                 for (int j = y; j; j -= lowbit(j))
     42 
     43                     res += arr[i][j];
     44             return res;
     45         }
     46     } T1, T2, T3, T4;
     47     void add(int x, int y, int n)
     48     {
     49         T1.add(x, y, n);
     50         T2.add(x, y, y * n);
     51         T3.add(x, y, x * n);
     52         T4.add(x, y, x * y * n);
     53     }
     54     X sum(int x, int y)
     55     {
     56         return (x + 1) * (y + 1) * T1.sum(x, y) - (x + 1) * T2.sum(x, y) - (y + 1) * T3.sum(x, y) + T4.sum(x, y);
     57     }
     58 
     59   public:
     60     void init()
     61     {
     62         CLR(T1.arr, 0);
     63         CLR(T2.arr, 0);
     64         CLR(T3.arr, 0);
     65         CLR(T4.arr, 0);
     66     }
     67     void update(int L, int B, int R, int T, int n)
     68     {
     69         add(L, B, n);
     70         add(L, T + 1, -n);
     71         add(R + 1, B, -n);
     72         add(R + 1, T + 1, n);
     73     }
     74     X query(int L, int B, int R, int T)
     75     {
     76         return sum(R, T) - sum(L - 1, T) - sum(R, B - 1) + sum(L - 1, B - 1);
     77     }
     78 };
     79 ④单点增减(add) + 立方体求和(query)
     80 ⑤立方体增减(update) + 单点求值(sum)
     81 int arr[MAXN][MAXN][MAXN];
     82 inline int sum(int x,int y,int z){
     83     int res = 0;
     84     for (int i = x; i; i -= lowbit(i))
     85         for (int j = y; j; j -= lowbit(j))
     86             for (int k = z; k; k -= lowbit(k))
     87                 res ^= arr[i][j][k];
     88     return res;
     89 }
     90 inline void add(int x,int y,int z,int n){
     91     for (int i = x; i < MAXN; i += lowbit(i))
     92         for (int j = y; j < MAXN; j += lowbit(j))
     93             for (int k = z; k < MAXN; k += lowbit(k))
     94                 arr[i][j][k] += n;
     95 }
     96 inline void update(int x1,int y1,int z1,int x2,int y2,int z2,int n){
     97     add(x1, y1, z1, n);
     98     add(x2 + 1, y1, z1, -n);
     99     add(x1, y2 + 1, z1, -n);
    100     add(x1, y1, z2 + 1, -n);
    101     add(x2 + 1, y2 + 1, z1, n);
    102     add(x2 + 1, y1, z2 + 1, n);
    103     add(x1, y2 + 1, z2 + 1, n);
    104     add(x2 + 1, y2 + 1, z2 + 1, -n);
    105 }
    106 inline int query(int x1,int y1,int z1,int x2,int y2,int z2){
    107     return sum(x2, y2, z2) - sum(x2, y2, z1 - 1) - sum(x2, y1 - 1, z2) - sum(x1 - 1, y2, z2) + sum(x2, y1 - 1, z1 - 1) + sum(x1 - 1, y2, z1 - 1) + sum(x1 - 1, y1 - 1, z2) - sum(x1 - 1, y1 - 1, z1 - 1);
    108 }
    109 
    110  
    111 ⑥立方体增减(update) + 立方体求和(query)///随便写写……复杂度较高
    112 template<typename X>
    113 class tree_array_Cube{
    114     struct tree_array_single
    115     {
    116         X arr[MAXN][MAXN][MAXN];
    117         X sum(int x, int y, int z)
    118         {
    119             X res = 0;
    120             for (int i = x; i; i -= lowbit(i))
    121                 for (int j = y; j; j -= lowbit(j))
    122                     for (int k = z; k; k -= lowbit(k))
    123                         res += arr[i][j][k];
    124             return res;
    125         }
    126         void add(int x, int y, int z, X n)
    127         {
    128             for (int i = x; i < MAXN; i += lowbit(i))
    129                 for (int j = y; j < MAXN; j += lowbit(j))
    130                     for (int k = z; k < MAXN; k += lowbit(k))
    131                         arr[i][j][k] += n;
    132         }
    133     } T1, T2, T3, T4, T5, T6, T7, T8;
    134     void add(int x, int y, int z, X n)
    135     {
    136         T1.add(x, y, z, n);
    137         T2.add(x, y, z, x * n);
    138         T3.add(x, y, z, y * n);
    139         T4.add(x, y, z, z * n);
    140         T5.add(x, y, z, x * y * n);
    141         T6.add(x, y, z, y * z * n);
    142         T7.add(x, y, z, x * z * n);
    143         T8.add(x, y, z, x * y * z * n);
    144     }
    145     X sum(int x, int y, int z)
    146     {
    147         return (x + 1) * (y + 1) * (z + 1) * T1.sum(x, y, z) - (y + 1) * (z + 1) * T2.sum(x, y, z) - (x + 1) * (z + 1) * T3.sum(x, y, z) - (x + 1) * (y + 1) * T4.sum(x, y, z) + (z + 1) * T5.sum(x, y, z) + (x + 1) * T6.sum(x, y, z) + (y + 1) * T7.sum(x, y, z) - T8.sum(x, y, z);
    148     }
    149 
    150   public:
    151     void init()
    152     {
    153         CLR(T1.arr, 0);
    154         CLR(T2.arr, 0);
    155         CLR(T3.arr, 0);
    156         CLR(T4.arr, 0);
    157         CLR(T5.arr, 0);
    158         CLR(T6.arr, 0);
    159         CLR(T7.arr, 0);
    160         CLR(T8.arr, 0);
    161     }
    162     void update(int x1, int y1, int z1, int x2, int y2, int z2, X n)
    163     {
    164         add(x1, y1, z1, n);
    165         add(x2 + 1, y1, z1, -n);
    166         add(x1, y2 + 1, z1, -n);
    167         add(x1, y1, z2 + 1, -n);
    168         add(x2 + 1, y2 + 1, z1, n);
    169         add(x2 + 1, y1, z2 + 1, n);
    170         add(x1, y2 + 1, z2 + 1, n);
    171         add(x2 + 1, y2 + 1, z2 + 1, -n);
    172     }
    173     X query(int x1, int y1, int z1, int x2, int y2, int z2)
    174     {
    175         return sum(x2, y2, z2) - sum(x2, y2, z1 - 1) - sum(x2, y1 - 1, z2) - sum(x1 - 1, y2, z2) + sum(x2, y1 - 1, z1 - 1) + sum(x1 - 1, y2, z1 - 1) + sum(x1 - 1, y1 - 1, z2) - sum(x1 - 1, y1 - 1, z1 - 1);
    176     }
    177 };
    15、多维树状数组
     1 inline void init()
     2 {
     3     CLR(arr, 0);
     4     for (int i = 1; i <= N; ++i)
     5         for (int j = i; j <= N && arr[j] < num[i]; j += lowbit(j))
     6             arr[j] = num[i];
     7 }
     8 inline int query(int L,int R)
     9 {
    10     int res = 0;
    11     for (--L; L < R;)
    12     {
    13         if (R - lowbit(R) >= L)
    14         {
    15             res = max(res, arr[R]);
    16             R -= lowbit(R);
    17         }
    18         else
    19         {
    20             res = max(res, num[R]);
    21             --R;
    22         }
    23     }
    24     return res;
    25 }
    26 inline void update(int x,int val)
    27 {
    28     int ori = num[x];
    29     num[x] = val;
    30     if (val >= ori)
    31         for (int i = x; i <= N && arr[i] < val; i += lowbit(i))
    32             arr[i] = val;
    33     else
    34     {
    35         for (int i = x; i <= N && arr[i] == ori; i += lowbit(i))
    36         {
    37             arr[i] = val;
    38             for (int j = lowbit(i) >> 1; j; j >>= 1)
    39                 arr[i] = max(arr[i], arr[i - j]);
    40         }
    41     }
    42 }
    16、树状数组—区间最大值
  • 相关阅读:
    分享15个Linux 实用技巧,提高工作效率
    隐藏搜索框:CSS 动画正反向序列
    js检测开发者工具是否打开,防止别人恶意调试我们的代码
    Js实现元素右滑回弹效果(基于Uniapp)
    css ::marker伪元素,修改li的项目符号颜色,字号字体
    Jump Game II
    Google 面经 09/26
    Word Search
    Remove Duplicates from Sorted List
    Remove Duplicates from Sorted List II
  • 原文地址:https://www.cnblogs.com/cdyboke/p/4925084.html
Copyright © 2011-2022 走看看