import java.util.*; import java.io.*; public class Solution { static long MOD = 1000000007L; static long[] fact; static void calculate() { fact = new long[100001]; fact[0] = 1; fact[1] = 1; for(int i=2;i<=100000;i++) { fact[i] = (fact[i-1]*(long)i)%MOD; } } public static void main(String[] args) throws Exception{ InputReader in = new InputReader(System.in); calculate(); char[] str = in.next().toCharArray(); int n = str.length; int[][] count = new int[n][26]; for(int i=0;i0) { val-=count[l-1][j]; } if(val%2==0 && val!=0) { even++; div[j] = val/2; } else if(val%2==1) { odd++; } } //System.out.println("e " + even + " " + odd); long rslt = 0; if(even>0 && odd>0) { long now = fact[even]; for(int j=0;j<26;j++) { // if(div[j]<=1) { // continue; // } now = now/fact[div[j]]; //System.out.println("n " +now + " " +j + " " + div[j]); now%=MOD; } rslt = now*odd; rslt+=MOD; rslt%=MOD; } else if(odd==0 && even>0) { rslt = fact[even]; } System.out.println(rslt); } } public static void MergeSort(int[] A, int lo, int hi) { if(lomid) { Arr[k++] = A[q++]; } else if(q>hi) { Arr[k++] = A[p++]; } else if(A[p]key) { hi = mid-1; } else { lo = mid+1; } } return -1; } public static int upperBound(int[] A, int key, int lo, int hi) { while(lo<=hi) { int mid = (lo+hi)/2; if(A[mid]>key && (mid==1 || A[mid-1]<=key)) { return mid; } else if(A[mid]>key) { hi = mid-1; } else { lo = mid+1; } } return -1; } public static int lowerBound(int[] A, int key, int lo, int hi) { while(lo<=hi) { int mid = (lo+hi)/2; if(A[mid]>=key && (mid==1 || A[mid-1]=key) { hi = mid-1; } else { lo = mid+1; } } return -1; } public static int power(int x, int n) { if(n==0) { return 1; } if(n==1) { return x; } int ret = power(x,n/2); int val = ret*ret; if(n%2==1) { val*=x; } return val; } public static int[][] sparseTable(int[] A, int n) { int logN = (int)(Math.log(n)/Math.log(2)); int[][] M = new int[n][logN+1]; for(int i=0;iend || rangeEnd=end) { return segmentTree[index]; } int mid = (start+end)/2; int val1 = query(A,segmentTree, start, mid, index*2+1, rangeStart, rangeEnd); int val2 = query(A,segmentTree, mid+1, end, index*2+2, rangeStart, rangeEnd); if(val1==-1) { return val2; } if(val2==-1) { return val1; } if(A[val1]<=A[val2]) { return val1; } return val2; } public static void constructSegmentTree(int[] A, int n) { int x = (int)Math.ceil(Math.log(n)/Math.log(2)); int size = (int)Math.pow(2,x+1)-1; int[] segmentTree = new int[size+1]; initialize(A,segmentTree,0,n-1,0); //update update(A,segmentTree,0,n-1,0,4,10); //query int ret = query(A,segmentTree,0,n-1,0,9,9); } //Z Algorithm public static int[] createLCPArray(String str) { int len = str.length(); int[] lcp = new int[len]; int L=0,R=0; lcp[0] = 0; for(int i=1;iR) { L=R=i; while(R>5)+2]; int sqrtN = (int)Math.sqrt(N); for(int i=3;i<=sqrtN;i+=2) { if(!check(status[i>>5],i&31)) { for(int j=i*i;j<=N;j+=(i<<1)) { status[j>>5] = set(status[j>>5],j&31); } } } int[] prime = new int[N]; int cnt=0; prime[cnt++]=2; for(int i=3;i<=N;i+=2) { if(!check(status[i>>5],i&31)) { prime[cnt++]=i; } } return prime; } public static int[][][] FibonacciGeneration(int P) { int[][][] A = new int[P][2][2]; A[0][0][0] = 1; A[0][0][1] = 1; A[0][1][0] = 1; A[0][1][1] = 0; for(int i=1;i=0;i--) { if((T&(1<