import java.awt.Dimension; import java.awt.Point; import java.io.*; import java.math.BigInteger; import java.util.*; import java.util.function.*; class Main{ static SimpleScanner sc=new SimpleScanner(System.in); static SimpleWriter out=new SimpleWriter(System.out); public static void main(String[]args){ int H=sc.nextInt(); int W=sc.nextInt(); var A=new Matrix(H,W); for(int i=0;i0;--i)inFact[i-1]=inFact[i]*i%mod;inFact[0]=1;this.mod=mod;} long getFact(int num){return fact[num];} long getInFact(int num){return inFact[num];} long getInverse(int num){return fact[num-1]*inFact[num]%mod;} long getCombi(int a,int b){if(a0){ array[temp++]=i; } } } static void insertSort(int[] array){ insertSort(array,0,array.length); } static void insertSort(int[] array,int l,int r){ for(int i=l+1;inum){ array[j]=array[j-1]; --j; } array[j]=num; } } static void insertSort(long[] array){ insertSort(array,0,array.length); } static void insertSort(long[] array,int l,int r){ for(int i=l+1;inum){ array[j]=array[j-1]; --j; } array[j]=num; } } static void insertSort(char[] array){ insertSort(array,0,array.length); } static void insertSort(char[] array,int l,int r){ for(int i=l+1;inum){ array[j]=array[j-1]; --j; } array[j]=num; } } static > void insertSort(E[] array){ insertSort(array,0,array.length); } static > void insertSort(E[] array,int l,int r){ for(int i=l+1;i0){ array[j]=array[j-1]; --j; } array[j]=num; } } static void reverseInsertSort(int[] array){ reverseInsertSort(array,0,array.length); } static void reverseInsertSort(int[] array,int l,int r){ for(int i=l+1;i> void reverseInsertSort(E[] array){ reverseInsertSort(array,0,array.length); } static > void reverseInsertSort(E[] array,int l,int r){ for(int i=l+1;i E[][] rotateR(E[][] array,E[][] ans){ for(int i=0;iarray[k][ans.length-index-1]); } return ans; } static long[][] rotateL(long[][] array){ long[][] ans=new long[array[0].length][array.length]; for(int i=0;iarray[k][ans.length-index-1]); } return ans; } static char[][] rotateL(char[][] array){ char[][] ans=new char[array[0].length][array.length]; for(int i=0;i E[][] rotateL(E[][] array,E[][] ans){ for(int i=0;i> route){ int[] count=new int[route.size()]; int pathCount=0; for(ArrayList path: route){ for(int point: path){ ++pathCount; ++count[point]; } } ArrayDeque deq=new ArrayDeque<>(); for(int i=1;i0){ int nowP=deq.pollFirst(); for(int nextP: route.get(nowP)){ ans[index][0]=nowP; ans[index++][1]=nextP; if(--count[nextP]==0){ deq.add(nextP); } } } return ans; } static int[][] topologicalSort(int[][] route){ int[] count=new int[route.length]; int pathCount=0; for(int[] path: route){ for(int point: path){ ++pathCount; ++count[point]; } } ArrayDeque deq=new ArrayDeque<>(); for(int i=1;i0){ int nowP=deq.pollFirst(); for(int nextP: route[nowP]){ ans[index][0]=nowP; ans[index++][1]=nextP; if(--count[nextP]==0){ deq.add(nextP); } } } return ans; } static void swap(int[] array,int a,int b){ int temp=array[a]; array[a]=array[b]; array[b]=temp; } static void swap(long[] array,int a,int b){ long temp=array[a]; array[a]=array[b]; array[b]=temp; } static void swap(double[] array,int a,int b){ double temp=array[a]; array[a]=array[b]; array[b]=temp; } static void swap(char[] array,int a,int b){ char temp=array[a]; array[a]=array[b]; array[b]=temp; } static void swap(boolean[] array,int a,int b){ boolean temp=array[a]; array[a]=array[b]; array[b]=temp; } static void swap(E[] array,int a,int b){ E temp=array[a]; array[a]=array[b]; array[b]=temp; } static void swap(int[][] array,int a,int b,int c,int d){ int temp=array[a][b]; array[a][b]=array[c][d]; array[c][d]=temp; } static void swap(long[][] array,int a,int b,int c,int d){ long temp=array[a][b]; array[a][b]=array[c][d]; array[c][d]=temp; } static void swap(double[][] array,int a,int b,int c,int d){ double temp=array[a][b]; array[a][b]=array[c][d]; array[c][d]=temp; } static void swap(char[][] array,int a,int b,int c,int d){ char temp=array[a][b]; array[a][b]=array[c][d]; array[c][d]=temp; } static void swap(boolean[][] array,int a,int b,int c,int d){ boolean temp=array[a][b]; array[a][b]=array[c][d]; array[c][d]=temp; } static void swap(E[][] array,int a,int b,int c,int d){ E temp=array[a][b]; array[a][b]=array[c][d]; array[c][d]=temp; } static boolean nextPermutation(int[] array){ int index1=0; for(int i=1;i> boolean nextPermutation(E[] array){ int index1=0; for(int i=1;iarray[i]){ index1=i; } } if(--index1<0){ return false; } int index2=0; int max=Integer.MIN_VALUE; for(int i=index1+1;iarray[i]){ index1=i; } } if(--index1<0){ return false; } int index2=0; long max=Long.MIN_VALUE; for(int i=index1+1;iarray[i]){ index1=i; } } if(--index1<0){ return false; } int index2=0; int max=Integer.MIN_VALUE; for(int i=index1+1;i> boolean previousPermutation(E[] array){ int index1=0; for(int i=1;i0){ index1=i; } } if(--index1<0){ return false; } int index2=0; E max=MathFunction.min(array); for(int i=index1+1;i void reverseRange(E[] array,int l,int r){ while(l mo_sComparator(int M){ return (a,b)->a[0]/M!=b[0]/M?Integer.compare(a[0]/M,b[0]/M): Integer.compare(a[1]/M,b[1]/M)*((a[0]/M&1)==0?-1:1); } } class MathFunction{ static int[] numberForIntPrime={2,7,61}; static long[] numberForLongPrime={2,7,61,325,9375,28178,450775,9780504,1795265022}; static long gcd(long a,long b){ a=Math.abs(a); b=Math.abs(b); if(b==0){ return a; } long temp; while((temp=a%b)!=0){ a=b; b=temp; } return b; } static long lcm(long a,long b){ return a/gcd(a,b)*b; } static boolean isPrime(long n){ n=Math.abs(n); if(n==2L){ return true; } if(n==1L||(n&1L)==0L){ return false; } if(n<=4_759_123_141L){ return isPrimeForInt(n); } return isPrimeForBigInteger(n); } static boolean isPrimeForInt(long n){ long d=n-1; while((d&1)==0L){ d >>= 1; } for(long a: numberForIntPrime){ if(a>=n){ return true; } long t=d; long y=MathFunction.modPow(a,t,n); while(t>= 1; } BigInteger bigN=BigInteger.valueOf(n); BigInteger bigNSubOne=bigN.subtract(BigInteger.ONE); BigInteger bigD=BigInteger.valueOf(d); for(long a: numberForLongPrime){ if(a>=n){ return true; } BigInteger t=bigD; BigInteger y=BigInteger.valueOf(a).modPow(t,bigN); while(t.compareTo(bigNSubOne)<0&&!y.equals(BigInteger.ONE)&&!y.equals(bigNSubOne)){ y=y.multiply(y).mod(bigN); t=t.shiftLeft(1); } if(!y.equals(bigNSubOne)&&(t.intValue()&1)==0){ return false; } } return true; } static int[] primes(int num){ if(num<2){ return new int[0]; } BitSet numbers=new BitSet(num+1); numbers.set(2,num+1); int limit=(int)Math.sqrt(num); int bit=0; while( rangeCheckClose( bit=numbers.nextSetBit(bit+1), 2, limit)){ for(int j=bit*bit;j<=num;j+=bit){ numbers.clear(j); } } int[] answer=new int[numbers.cardinality()]; bit=0; for(int i=0;i0){ if((b&1)==1){ ans *= a; } a *= a; b >>= 1; } return ans; } static long modPow(long a,long b,long mod){ long ans=1; a %= mod; while(b>0){ if((b&1)==1){ ans *= a; } ans %= mod; a *= a; a %= mod; b >>= 1; } return ans; } static long fact(int N){ long ans=1; for(int i=2;i<=N;++i){ ans *= i; } return ans; } static long modFact(int N,long mod){ long ans=1; for(int i=2;i<=N;++i){ ans *= i; ans %= mod; } return ans; } static long combi(long n,long r){ if(r<0||n0||temp2>0){ return -1; } if(temp1==0&&temp2==0){ return 0; } return 1; } static int isCrossed(Point p1,Point p2,Point p3,Point p4){ return isCrossed(p1.x,p1.y,p2.x,p2.y,p3.x,p3.y,p4.x,p4.y); } static boolean isConvex(Point... points){ int n=points.length; if(n<3){ return false; } if(n==3){ return true; } boolean conv=true; for(int i=0;i=0; } return conv; } static long remainder(long num,long mod){ num %= mod; if(num<0){ num += mod; } return num; } static int digit(long num){ if(num<10L){ return 1; } if(num<100L){ return 2; } if(num<1000L){ return 3; } if(num<10000L){ return 4; } if(num<100000L){ return 5; } if(num<1000000L){ return 6; } if(num<10000000L){ return 7; } if(num<100000000L){ return 8; } if(num<1000000000L){ return 9; } if(num<10000000000L){ return 10; } if(num<100000000000L){ return 11; } if(num<1000000000000L){ return 12; } if(num<10000000000000L){ return 13; } if(num<100000000000000L){ return 14; } if(num<1000000000000000L){ return 15; } if(num<10000000000000000L){ return 16; } if(num<100000000000000000L){ return 17; } if(num<1000000000000000000L){ return 18; } return 19; } static int max(int... nums){ int ans=Integer.MIN_VALUE; for(int num: nums){ ans=Math.max(ans,num); } return ans; } static long max(long... nums){ long ans=Long.MIN_VALUE; for(long num: nums){ ans=Math.max(ans,num); } return ans; } static double max(double... nums){ double ans=-Double.MIN_VALUE; for(double num: nums){ ans=Math.max(ans,num); } return ans; } static > E max(E[] nums){ E ans=nums[0]; for(E value: nums){ if(ans.compareTo(value)<0){ ans=value; } } return ans; } static int min(int... nums){ int ans=Integer.MAX_VALUE; for(int num: nums){ ans=Math.min(ans,num); } return ans; } static long min(long... nums){ long ans=Long.MAX_VALUE; for(long num: nums){ ans=Math.min(ans,num); } return ans; } static double min(double... nums){ double ans=Double.MAX_VALUE; for(double num: nums){ ans=Math.min(ans,num); } return ans; } static > E min(E[] nums){ E ans=nums[0]; for(E value: nums){ if(ans.compareTo(value)>0){ ans=value; } } return ans; } static long sum(int... nums){ long ans=0; for(int num: nums){ ans += num; } return ans; } static long sum(long... nums){ long ans=0; for(long num: nums){ ans += num; } return ans; } static long modSum(long mod,int... nums){ long ans=0; for(int num: nums){ ans += num; ans %= mod; } if(ans<0){ ans += mod; } return ans; } static long modSum(long mod,long... nums){ long ans=0; for(long num: nums){ ans += num; ans %= mod; } if(ans<0){ ans += mod; } return ans; } static long sum(int[] nums,int from,int to){ long ans=0; for(int i=from;i> boolean rangeCheck(E num,E l,E r){ return 0<=num.compareTo(l)&&num.compareTo(r)<0; } static boolean rangeCheckOpen(int num,int l,int r){ return l> boolean rangeCheckOpen(E num,E l,E r){ return 0> boolean rangeCheckClose(E num,E l,E r){ return 0<=num.compareTo(l)&&num.compareTo(r)<=0; } static boolean rangeCheckSubClose(int num,int l,int r){ return l> boolean rangeCheckSubClose(E num,E l,E r){ return 0value){ b=c-1; } else{ a=(ans=c)+1; } } return ans; } static int downSearch(long[] array,long value){ int a=0, b=array.length-1, ans=-1, c; while(a-b<1){ c=(a+b)/2; if(array[c]>value){ b=c-1; } else{ a=(ans=c)+1; } } return ans; } static int downSearch(double[] array,double value){ int a=0, b=array.length-1, ans=-1, c; while(a-b<1){ c=(a+b)/2; if(array[c]>value){ b=c-1; } else{ a=(ans=c)+1; } } return ans; } static int downSearch(char[] array,int value){ int a=0, b=array.length-1, ans=-1, c; while(a-b<1){ c=(a+b)/2; if(array[c]>value){ b=c-1; } else{ a=(ans=c)+1; } } return ans; } static > int downSearch(E[] array,E value){ int a=0, b=array.length-1, ans=-1, c; while(a-b<1){ c=(a+b)/2; if(array[c].compareTo(value)>0){ b=c-1; } else{ a=(ans=c)+1; } } return ans; } static > int downSearch(List list,E value){ int a=0, b=list.size()-1, ans=-1, c; while(a-b<1){ c=(a+b)/2; if(list.get(c).compareTo(value)>0){ b=c-1; } else{ a=(ans=c)+1; } } return ans; } static int downSearch(int a,int b,int value,IntUnaryOperator func){ int ans=a-1, c; while(a-b<1){ c=(a+b)/2; if(func.applyAsInt(c)>value){ b=c-1; } else{ a=(ans=c)+1; } } return ans; } static long downSearch(long a,long b,long value,LongUnaryOperator func){ long ans=a-1, c; while(a-b<1){ c=(a+b)/2; if(func.applyAsLong(c)>value){ b=c-1; } else{ a=(ans=c)+1; } } return ans; } static double search(double a,double b,double value,DoubleUnaryOperator func){ double ans=a-Math.abs(a), c; for(int $=0;$value){ b=c; } else{ a=(ans=c); } } return ans; } static boolean contains(int[] array,int value){ int a=0, b=array.length-1, c; while(a-b<1){ c=(a+b)/2; if(array[c]>value){ b=c-1; } else if(array[c]value){ b=c-1; } else if(array[c]value){ b=c-1; } else if(array[c]value){ b=c-1; } else if(array[c]> boolean contains(E[] array,E value){ int a=0, b=array.length-1, c; while(a-b<1){ c=(a+b)/2; int result=array[c].compareTo(value); if(result>0){ b=c-1; } else if(result<0){ a=c+1; } else{ return true; } } return false; } static > boolean contains(List list,E value){ int a=0, b=list.size()-1, c; while(a-b<1){ c=(a+b)/2; int result=list.get(c).compareTo(value); if(result>0){ b=c-1; } else if(result<0){ a=c+1; } else{ return true; } } return false; } static boolean contains(int a,int b,int value,IntUnaryOperator func){ int c; while(a-b<1){ c=(a+b)/2; int num=func.applyAsInt(c); if(num>value){ b=c-1; } else if(numvalue){ b=c-1; } else if(numvalue){ b=c-1; } else if(numvalue){ b=c-1; } else if(array[c]value){ b=c-1; } else if(array[c]value){ b=c-1; } else if(array[c]value){ b=c-1; } else if(array[c]> int search(E[] array,E value){ int a=0, b=array.length-1, c; while(a-b<1){ c=(a+b)/2; int result=array[c].compareTo(value); if(result>0){ b=c-1; } else if(result<0){ a=c+1; } else{ return c; } } return -1; } static > int search(List list,E value){ int a=0, b=list.size()-1, c; while(a-b<1){ c=(a+b)/2; int result=list.get(c).compareTo(value); if(result>0){ b=c-1; } else if(result<0){ a=c+1; } else{ return c; } } return -1; } static int search(int a,int b,int value,IntUnaryOperator func){ int c; while(a-b<1){ c=(a+b)/2; int num=func.applyAsInt(c); if(num>value){ b=c-1; } else if(numvalue){ b=c-1; } else if(num=value){ b=(ans=c)-1; } else{ a=c+1; } } return ans; } static int upSearch(long[] array,long value){ int a=0, b=array.length-1, ans=array.length, c; while(a-b<1){ c=(a+b)/2; if(array[c]>=value){ b=(ans=c)-1; } else{ a=c+1; } } return ans; } static int upSearch(double[] array,double value){ int a=0, b=array.length-1, ans=array.length, c; while(a-b<1){ c=(a+b)/2; if(array[c]>=value){ b=(ans=c)-1; } else{ a=c+1; } } return ans; } static int upSearch(char[] array,char value){ int a=0, b=array.length-1, ans=array.length, c; while(a-b<1){ c=(a+b)/2; if(array[c]>=value){ b=(ans=c)-1; } else{ a=c+1; } } return ans; } static > int upSearch(E[] array,E value){ int a=0, b=array.length-1, ans=array.length, c; while(a-b<1){ c=(a+b)/2; if(array[c].compareTo(value)>=0){ b=(ans=c)-1; } else{ a=c+1; } } return ans; } static > int upSearch(List list,E value){ int a=0, b=list.size()-1, ans=list.size(), c; while(a-b<1){ c=(a+b)/2; if(list.get(c).compareTo(value)>=0){ b=(ans=c)-1; } else{ a=c+1; } } return ans; } static int upSearch(int a,int b,int value,IntUnaryOperator func){ int ans=b+1, c; while(a-b<1){ c=(a+b)/2; if(func.applyAsInt(c)>=value){ b=(ans=c)-1; } else{ a=c+1; } } return ans; } static long upSearch(long a,long b,long value,LongUnaryOperator func){ long ans=b+1, c; while(a-b<1){ c=(a+b)/2; if(func.applyAsLong(c)>=value){ b=(ans=c)-1; } else{ a=c+1; } } return ans; } static int underSearch(int[] array,int value){ int a=0, b=array.length-1, ans=-1, c; while(a-b<1){ c=(a+b)/2; if(array[c]>=value){ b=c-1; } else{ a=(ans=c)+1; } } return ans; } static int underSearch(long[] array,long value){ int a=0, b=array.length-1, ans=-1, c; while(a-b<1){ c=(a+b)/2; if(array[c]>=value){ b=c-1; } else{ a=(ans=c)+1; } } return ans; } static int underSearch(double[] array,double value){ int a=0, b=array.length-1, ans=-1, c; while(a-b<1){ c=(a+b)/2; if(array[c]>=value){ b=c-1; } else{ a=(ans=c)+1; } } return ans; } static int underSearch(char[] array,char value){ int a=0, b=array.length-1, ans=-1, c; while(a-b<1){ c=(a+b)/2; if(array[c]>=value){ b=c-1; } else{ a=(ans=c)+1; } } return ans; } static > int underSearch(E[] array,E value){ int a=0, b=array.length-1, ans=-1, c; while(a-b<1){ c=(a+b)/2; if(array[c].compareTo(value)>=0){ b=c-1; } else{ a=(ans=c)+1; } } return ans; } static > int underSearch(List list,E value){ int a=0, b=list.size()-1, ans=-1, c; while(a-b<1){ c=(a+b)/2; if(list.get(c).compareTo(value)>=0){ b=c-1; } else{ a=(ans=c)+1; } } return ans; } static int underSearch(int a,int b,int value,IntUnaryOperator func){ int ans=a-1, c; while(a-b<1){ c=(a+b)/2; if(func.applyAsInt(c)>=value){ b=c-1; } else{ a=(ans=c)+1; } } return ans; } static long underSearch(long a,long b,long value,LongUnaryOperator func){ long ans=a-1, c; while(a-b<1){ c=(a+b)/2; if(func.applyAsLong(c)>=value){ b=c-1; } else{ a=(ans=c)+1; } } return ans; } static int overSearch(int[] array,int value){ int a=0, b=array.length-1, ans=array.length, c; while(a-b<1){ c=(a+b)/2; if(array[c]>value){ b=(ans=c)-1; } else{ a=c+1; } } return ans; } static int overSearch(long[] array,long value){ int a=0, b=array.length-1, ans=array.length, c; while(a-b<1){ c=(a+b)/2; if(array[c]>value){ b=(ans=c)-1; } else{ a=c+1; } } return ans; } static int overSearch(double[] array,double value){ int a=0, b=array.length-1, ans=array.length, c; while(a-b<1){ c=(a+b)/2; if(array[c]>value){ b=(ans=c)-1; } else{ a=c+1; } } return ans; } static int overSearch(char[] array,char value){ int a=0, b=array.length-1, ans=array.length, c; while(a-b<1){ c=(a+b)/2; if(array[c]>value){ b=(ans=c)-1; } else{ a=c+1; } } return ans; } static > int overSearch(E[] array,E value){ int a=0, b=array.length-1, ans=array.length, c; while(a-b<1){ c=(a+b)/2; if(array[c].compareTo(value)>0){ b=(ans=c)-1; } else{ a=c+1; } } return ans; } static > int overSearch(List list,E value){ int a=0, b=list.size()-1, ans=list.size(), c; while(a-b<1){ c=(a+b)/2; if(list.get(c).compareTo(value)>0){ b=(ans=c)-1; } else{ a=c+1; } } return ans; } static int overSearch(int a,int b,int value,IntUnaryOperator func){ int ans=b+1, c; while(a-b<1){ c=(a+b)/2; if(func.applyAsInt(c)>value){ b=(ans=c)-1; } else{ a=c+1; } } return ans; } static long overSearch(long a,long b,long value,LongUnaryOperator func){ long ans=b+1, c; while(a-b<1){ c=(a+b)/2; if(func.applyAsLong(c)>value){ b=(ans=c)-1; } else{ a=c+1; } } return ans; } static int linearSearch(int[] array,int value){ for(int i=0;i> int linearSearch(E[] array,E value){ for(int i=0;i> int linearSearch(List list,E value){ for(int i=0;i>= 1; } return a; } static Matrix modPow(Matrix original,Matrix pw,long exp,long mod){ Matrix a=original.copy(); Matrix b=pw.copy(); while(0>= 1; } return a; } long determinant(){ return determinant(matrix); } static long determinant(long[][] mat){ assert mat.length==mat[0].length; if(mat.length==1){ return mat[0][0]; } if(mat.length==2){ return mat[0][0]*mat[1][1]-mat[0][1]*mat[1][0]; } int length = mat.length-1; long[][] miniMat=new long[mat.length-1][mat.length-1]; long ans = 0; for(int i=0;i{ static long BASE=new Random().nextInt(1000)+Character.MAX_VALUE+1,MASK30=(1L<<30)-1,MASK31=(1L<<31)-1,MOD=(1L<<61)-1,MASK61=MOD; long[]hash; String string; RollingHash(String str){string=str;hash=new long[str.length()+1];roll();} void roll(){int len=string.length();for(int i=1;i<=len;++i){hash[i]=multiply(hash[i-1],BASE)+string.charAt(i-1)-' '+1;if(MOD<=hash[i])hash[i]-=MOD;}} static long multiply(long a,long b){long au=a>>31,ad=a&MASK31,bu=b>>31,bd=b&MASK31,mid=ad*bu+au*bd,midu=mid>>30,midd=mid&MASK30;return mod(au*bu*2+midu+(midd<<31)+ad*bd);} static long mod(long x){long xu=x>>61,xd=x&MASK61,ans=xu+xd;if(MOD<=ans)ans-=MOD;return ans;} long getHash(int l,int r){return(hash[r]-multiply(hash[l],modBasePow(r-l))+MOD)%MOD;} static long modBasePow(long b){long ans=1,a=BASE;while(b>0){if((b&1)==1)ans=multiply(ans,a);a=multiply(a,a);b>>=1;}return ans;} boolean equals(RollingHash rh,int l1,int r1,int l2,int r2){return r1-l1!=r2-l2?false:getHash(l1,r1)==rh.getHash(l2,r2);} int length(){return string.length();} @Override public int hashCode(){return string.hashCode();} @Override public String toString(){return string;} @Override public boolean equals(Object o){return o instanceof RollingHash rh?equals(rh,0,length(),0,rh.length()):false;} @Override public int compareTo(RollingHash rh){return string.compareTo(rh.toString());} int compareTo(String str){return string.compareTo(str);} char charAt(int i){return string.charAt(i);} int compareToIgnoreCase(RollingHash rh){return string.compareToIgnoreCase(rh.toString());} int compareToIgnoreCase(String str){return string.compareToIgnoreCase(str);} void concat(RollingHash rh){concat(rh.toString());} void concat(String str){string=string.concat(str);hash=new long[string.length()+1];roll();} boolean contains(RollingHash rh){var hash=rh.getHash(0,rh.length());int len=length()-rh.length();for(int i=0;i<=len;++i)if(hash==getHash(i,rh.length()+i))return true;return false;} boolean contains(String str){return indexOf(str)!=-1;} int indexOf(int ch){return indexOf(ch,0);} int indexOf(int ch,int fromIndex){int len=length();for(int i=fromIndex;i=0;--i)if(string.charAt(i)==ch)return i;return -1;} int lastIndexOf(int ch){return lastIndexOf(ch,length()-1);} static RollingHash valueOf(boolean b){return new RollingHash(b?"true":"false");} static RollingHash valueOf(char c){return new RollingHash(""+c);} static RollingHash valueOf(char[] c){return new RollingHash(String.valueOf(c,0,c.length));} static RollingHash valueOf(char[] c,int offset,int count){return new RollingHash(String.valueOf(c,offset,count));} static RollingHash valueOf(double d){return new RollingHash(String.valueOf(d));} static RollingHash valueOf(float f){return new RollingHash(String.valueOf(f));} static RollingHash valueOf(int i){return new RollingHash(String.valueOf(i));} static RollingHash valueOf(long l){return new RollingHash(String.valueOf(l));} static RollingHash valueOf(Object obj){return new RollingHash(String.valueOf(obj));} } @SuppressWarnings("unchecked")abstract class SegmentTree{ int N,size; E def; Object[]node; SegmentTree(int n,E def,boolean is1indexed){int num=2;while(num>1)-(is1indexed?1:0);node=new Object[N];this.def=def;Arrays.fill(node,this.def);} SegmentTree(E[]arr,E def,boolean is1indexed){int num=2;while(num>1-(is1indexed?1:0);node=new Object[N];this.def=def;System.arraycopy(arr,0,node,N>>1,arr.length);for(int i=arr.length+(N>>1);i>1)-1;i>0;i--)node[i]=function((E)node[i<<1],(E)node[(i<<1)+1]);} void update(int n,E value){n+=size;node[n]=value;n>>=1;while(n>0){node[n]=function((E)node[n<<1],(E)node[(n<<1)+1]);n>>=1;}} E get(int a){return(E)node[a+size];} E answer(){return(E)node[1];} E query(int l,int r){l+=size;r+=size;E answer=def;while(l>0&&r>0&&l<=r){if(l%2==1)answer=function((E)node[l++],answer);l>>=1;if(r%2==0)answer=function(answer,(E)node[r--]);r>>=1;}return answer;} abstract E function(E a,E b); } @SuppressWarnings("unchecked")abstract class LazySegmentTree{ int size,log; S defaultS; F defaultF; S[]node; F[]lazy; LazySegmentTree(int N,S defaultS,F defaultF){this(N,defaultS,defaultF,false);} LazySegmentTree(int N,S defaultS,F defaultF,boolean is1indexed){this.log=32-Integer.numberOfLeadingZeros(N-1);this.size=(1<0;i--)node[i]=function(node[i<<1],node[i<<1|1]);} void spread(int index){if(lazy[index]!=defaultF){int l=index<<1,r=index<<1|1;node[l]=mapping(node[l],lazy[index]);node[r]=mapping(node[r],lazy[index]);lazy[l]=composition(lazy[l],lazy[index]);lazy[r]=composition(lazy[r],lazy[index]);lazy[index]=defaultF;}} void spreadLine(int from){for(int i=log;i>0;i--)spread(from>>i);} void spreadRange(int l,int r){for(int i=log;i>0;i--){if((l>>i<>i);if((r>>i<>i);}} void update(int index){while((index>>=1)>0)node[index]=function(node[index<<1],node[index<<1|1]);} void update(int l,int r){for(int i=1;i<=log;i++){int subL=l>>i,subR=r>>i;if((subL<>=1;r>>=1;}return function(sumL,sumR);} S answer(){return node[1];} void apply(int index,F f){index+=size;spreadLine(index);node[index]=mapping(node[index],f);update(index);} void apply(int l,int r,F f){l+=size;r+=size;spreadRange(l,r);int subL=l,subR=r;while(subL>=1;subR>>=1;}update(l,r);} abstract S function(S s1,S s2); abstract F composition(F f1,F f2); abstract S mapping(S s,F f); } class UnionFind{ int[]par,rank,size,path; int count; UnionFind(int N){count=N;par=new int[N];rank=new int[N];size=new int[N];path=new int[N];Arrays.fill(par,-1);Arrays.fill(size,1);} int root(int ind){return par[ind]==-1?ind:(par[ind]=root(par[ind]));} boolean isSame(int x,int y){return root(x)==root(y);} boolean unite(int x,int y){int rx=root(x);int ry=root(y);++path[rx];if(rx==ry)return false;if(rank[rx]' '){ans.append((char)c);c=read();}return ans.toString();} BigInteger nextBigInteger(){return new BigInteger(next());} byte[]nextByte(int n){var ans=new byte[n];for(int i=0;i0;i--){integerBuffer[i]=(byte)(num%10+ZERO);num/=10;}if(l<0)write(integerBuffer,0,len+1);else write(integerBuffer,1,len);}} void print(float f){write(String.valueOf(f).toCharArray());} void print(double d){write(String.valueOf(d).toCharArray());} void print(char[]s){write(s);} void print(Object obj){write(obj.toString().toCharArray());} void println(){newLine();} void println(boolean x){print(x);println();} void println(char x){print(x);println();} void println(int x){print(x);println();} void println(long x){print(x);println();} void println(float x){print(x);println();} void println(double x){print(x);println();} void println(char[]x){print(x);println();} void println(String x){print(x);println();} void println(Object x){print(x);println();} SimpleWriter printf(String format,Object...args){print(String.format(format,args));return this;} SimpleWriter append(CharSequence csq){write(String.valueOf(csq).toCharArray());return this;} SimpleWriter append(CharSequence csq,int start,int end){if(csq==null)csq="null";return append(csq.subSequence(start,end));} SimpleWriter append(char c){write(c);return this;} void print(int[]array){print(array,' ');} void print(int[]array,String str){if(array.length==0)return;print(array[0]);for(int i=1;ivoid print(E[]array){print(array,' ');} void print(E[]array,String str){print(array[0]);for(int i=1;ivoid print(E[]array,char c){print(array[0]);for(int i=1;ivoid print(E[][]arrays){print(arrays,' ');} void print(E[][]arrays,String str){print(arrays[0],str);for(int i=1;ivoid print(E[][]arrays,char c){print(arrays[0],c);for(int i=1;ivoid println(E[]array){println(array,' ');} void println(E[]array,String str){print(array,str);println();} void println(E[]array,char c){print(array,c);println();} void println(E[][]arrays){println(arrays,' ');} void println(E[][]arrays,String str){print(arrays,str);println();} void println(E[][]arrays,char c){print(arrays,c);println();} void println(Listlist){println(list,' ');} void println(Listlist,String str){if(list.size()>0){print(list.get(0));for(int i=1;ivoid println(Listlist,char c){if(list.size()>0){print(list.get(0));for(int i=1;i0){out.write(buf,0,count);count=0;}} void write(int b)throws IOException{if(count>=buf.length)flushBuffer();buf[count++]=(byte)b;} void write(char[]ch,int off,int len)throws IOException{if(len>=buf.length){flushBuffer();out.write(parseByteArray(ch,off,len),0,len);return;}if(len>buf.length-count)flushBuffer();for(int i=0;i=buf.length){flushBuffer();out.write(b,off,len);return;}if(len>buf.length-count)flushBuffer();System.arraycopy(b,off,buf,count,len);count+=len;} void flush() throws IOException{flushBuffer();out.flush();} void close() throws IOException{flush();out.close();out=null;} } }