n = gets.to_i
t, a = gets.split(" ").map(&:to_i)
hs = gets.split(" ").map(&:to_i)

array = []
hs.each_with_index do |h, i|
  average_temp = t - (h * 0.006)
#   p "#{i+1} #{average_temp} #{(a - average_temp).abs}"
  array << (a - average_temp).abs
end

puts array.index(array.min) + 1


N,T,A,*hs=$<.read.split.map(&:to_i)

n = 0
d = 10**9
hs.each.with_index do |h,i|
    t = T-h*0.006
    t = (A-t).abs
    if t < d
        n = i
        d = t
    end
end

puts n+1


n = gets.to_i
t, a = gets.split.map(&:to_i)
h = gets.split.map(&:to_i)

ans = 0
ccc = 1000000000000

(0..(n - 1)).each do |i|
  curr = i + 1
  temp = (t - h[i] * 6)
  ci = (a - temp).abs
  if ci < ccc
    ccc = ci
    ans = curr
  end
end
puts ans


n = gets.chomp.to_i
t, a = gets.chomp.split(' ').map(&:to_i)
list = gets.chomp.split(' ').map(&:to_i)

result = 1
temperature = t - (list[0] * 0.006).to_i

(1..(n-1)).each do |i|
  temp = t - (list[i] * 0.006).to_i

  if (a - temp) == 0
    result = i+1
    break
  end

  if (a - temperature).abs > (a - temp).abs
    result = i+1
    temperature = temp
  end
end

print result


n = gets.chomp.to_i
t, a = gets.chomp.split(' ').map(&:to_i)
list = gets.chomp.split(' ').map(&:to_i)

result = 1
temperature = t - (list[0] * 0.006).to_i

(1..(n-1)).each do |i|
  temp = t - (list[i] * 0.006).to_i

  if (a.abs - temp.abs) == 0
    result = i+1
    break
  end

  if (a > temp.abs && temp.abs > temperature.abs) || (temperature.abs > temp.abs && temp.abs > a)
    result = i+1
    temperature = temp
  end
end

print result


use std::io::*;
use std::str::FromStr;

pub fn read<T: FromStr>() -> T {
    let stdin = stdin();
    let stdin = stdin.lock();
    let token: String = stdin
        .bytes()
        .map(|c| c.expect("failed to read char") as char)
        .skip_while(|c| c.is_whitespace())
        .take_while(|c| !c.is_whitespace())
        .collect();
    token.parse().ok().expect("failed to parse token")
}

fn main() {
    let n: usize = read();
    let t: f64 = read();
    let a: f64 = read();
    let mut h: Vec<i64> = vec![];
    let mut ans = 0;

    for _ in 0..n {
        h.push(read());
    }

    let mut diff = (t - h[0] as f64 * 0.006 - a).abs();

    for i in 0..h.len() {
        let hi = h[i];
        if diff > (t - hi as f64 * 0.006 - a).abs() {
            diff = (t - hi as f64 * 0.006 - a).abs();
            ans = i;
        }
    }
    println!("{}", ans + 1);
}


macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
    ($($r:tt)*) => {
        let mut s = {
            use std::io::Read;
            let mut s = String::new();
            std::io::stdin().read_to_string(&mut s).unwrap();
            s
        };
        let mut iter = s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
}

macro_rules! input_inner {
    ($iter:expr) => {};
    ($iter:expr, ) => {};

    ($iter:expr, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($iter, $t);
        input_inner!{$iter $($r)*}
    };
}

macro_rules! read_value {
    ($iter:expr, ( $($t:tt),* )) => {
        ( $(read_value!($iter, $t)),* )
    };

    ($iter:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($iter, $t)).collect::<Vec<_>>()
    };

    ($iter:expr, chars) => {
        read_value!($iter, String).chars().collect::<Vec<char>>()
    };

    ($iter:expr, usize1) => {
        read_value!($iter, usize) - 1
    };

    ($iter:expr, $t:ty) => {
        $iter.next().unwrap().parse::<$t>().expect("Parse error")
    };
}

fn main() {
    input! {
        n: u32,
        t: i32,
        a: i32,
        h: [i32; n],
    };
    println!(
        "{}",
        h.iter()
            .map(|x| (1000 * a - (1000 * t - 6 * x)).abs())
            .enumerate()
            .min_by_key(|&(_, v)| v)
            .unwrap()
            .0
            + 1
    );
}


use std::io;

fn procon_read<T: std::str::FromStr>() ->  Vec<T> {
	let mut buf = String::new();
	io::stdin().read_line(&mut buf).expect("");
	let iter = buf.split_whitespace();
	let mut v: Vec<T> = Vec::new();
	for i in iter {
		v.push(i.parse().ok().unwrap());
	}
	v
}

fn main() {
	let v:Vec<i32> = procon_read();
	let n = v[0];
	let v:Vec<f64> = procon_read();
	let t = v[0];
	let a = v[1];
	let v:Vec<f64> = procon_read();
	let mut mini = (a - (t - v[0]*0.006)).abs();
	let mut p = 1;
	for i in 1..n {
		if mini.abs().min((a - (t - v[i as usize]*0.006)).abs()) != mini.abs() {
			mini = mini.abs().min((a - (t - v[i as usize]*0.006)).abs());
			p = i + 1;
		}
	}
	println!("{}", p);
}


use proconio::{fastout, input};

#[fastout]
fn main() {
    input!(n: usize, t: f64, a: f64, h: [f64; n]);

    let mut min = 100_000_000.0;
    let mut ans = 0;
    for i in 0..h.len() {
        let sa = (a - t - h[i] * 0.006).abs();

        if min >= sa {
            min = sa;
            ans = i;
        }
    }

    println!("{}", ans + 1);
}


use proconio::{input, fastout};
use std::cmp::*;

macro_rules! debug {
      ($($a:expr),*) => {
          eprintln!(concat!($(stringify!($a), " = {:?}, "),*), $($a),*);
      }
  }

#[fastout]
fn main() {
    input!{
        n: usize,
        t: usize,
        a: i64,
        h: [usize;n],
    }
    let INF = 100_0000;
    let mut minv = INF;
    let mut mini = 1;
    for i in 0..n {
        let te = (t as f64) - ((h[i] as f64) * 0.006);
        debug!((h[i] as f64) * 0.006);
        debug!(te);
        if minv > (a - te as i64).abs() {
            minv = (a - te as i64).abs();
            mini = i+1;
        }
    }

    println!("{}", mini);

}


use proconio::{input, fastout};
use std::cmp::*;

macro_rules! debug {
      ($($a:expr),*) => {
          eprintln!(concat!($(stringify!($a), " = {:?}, "),*), $($a),*);
      }
  }

#[fastout]
fn main() {
    input!{
        n: usize,
        t: usize,
        a: i64,
        h: [usize;n],
    }
    let INF = 1000_0000;
    let mut minv = INF;
    let mut mini = 1;
    for i in 0..n {
        let te = (t as f64) - ((h[i] as f64) * 0.006);
        debug!((h[i] as f64) * 0.006);
        debug!(te);
        if minv > (a - te as i64).abs() {
            minv = min(minv, (a - te as i64).abs());
            mini = i+1;
        }
    }

    println!("{}", mini);

}


let N = Int(readLine()!)!
let a = readLine()!.split(separator: " ").map({Int($0)!})
let T = a[0]
let A = a[1]

let H_line = readLine()!.split(separator: " ").map{abs(a[0]*1000 - 1000*a[1] - Int($0)! * 6)}
print(H_line.firstIndex(of: H_line.min()!)! + 1)


let N = Int(readLine()!)!
let a = readLine()!.split(separator: " ").map({Int($0)!})
let T = a[0]
let A = a[1]

let H_line = readLine()!.split(separator: " ").map({abs(T*1000 - 1000*A - Int($0)! * 6)})
print(H_line.firstIndex(of: H_line.min()!)! + 1)


_ = readLine()!
let ta = readLine()!.split(separator: " ").compactMap { Double($0) }
let t = ta[0]
let a = ta[1]
let h = readLine()!.split(separator: " ").compactMap { Double($0) }

let result = h.lazy
    .map { abs((t - $0 * 0.006) - a) }
    .enumerated()
    .min { $0.1 < $1.1 }!

print(result.0 + 1)


let N = Int(readLine()!)!
let a = readLine()!.split(separator: " ").map({Int($0)!})
let T = a[0]
let A = a[1]

let H_line = readLine()!.split(separator: " ").map({abs(A*1000 - 1000*T - Int($0)! * 6)})
print(H_line.firstIndex(of: H_line.min()!)! + 1)


let N = Int(readLine()!)!
let a = readLine()!.split(separator: " ").map({Double($0)!})
let T = a[0]
let A = a[1]

let H_line = readLine()!.split(separator: " ").map({abs(A - T - Double($0)! * 0.006)})
print(H_line.firstIndex(of: H_line.min()!)! + 1)


let N = Int(readLine()!)!
let a = readLine()!.split(separator: " ").map({Double($0)!})
let T = a[0]
let A = a[1]

let H_line = readLine()!.split(separator: " ").map({abs(A - T - Double($0)! * 0.006)})

var H_lineSorted = H_line.sorted()

var ans = H_line.index(of: H_lineSorted[0])
print(ans!+1)


const stdin = require('fs').readFileSync('/dev/stdin', 'utf8')

const _n = stdin.split('\n')[0]
const n = Number(_n)

const [t,a] = stdin.split('\n')[1].split(' ').map(Number)

const h = stdin.split('\n')[2].split(' ').map(Number)

let diffMin = Infinity

const temps = h.map(x=>{
  const tmp = t - x * 0.006
  return Math.abs(a-tmp)
})

const min = Math.min(...temps)

const ans = temps.indexOf(min) + 1

console.log(ans)


import * as fs from 'fs';

namespace AtCoder {
    class ABC113 {
        /**
         * @param inp
         * 2
         * 12 5
         * 1000 2000
         */
        main(inp: string): void {
            // t-x*0.006
            const [t, a]: number[] = inp.split('\n')[1].split(' ').map(x => parseInt(x, 10));
            let ans: number = 0;
            let tmpAbs: number = 9999999;
            inp.split('\n')[2].split(' ').forEach((h, index) => {
                const abs: number = Math.abs(a - (t - parseInt(h) * 0.006));
                if (tmpAbs > abs) {
                    tmpAbs = abs;
                    ans = index + 1;
                }
            });
            console.log(ans);
        }
    }

    const func = new ABC113();
    func.main(fs.readFileSync('/dev/stdin', 'utf8').trim());
}


const log = console.log;

const parseLines = (s: string) => s.trim().split("\n");
const parseSpaceSeparated = (line: string) => line.trim().split(" ");
const parseDecimalInt = (s: string) => parseInt(s);
const parseSpaceSeparatedDecimalInt = (line: string) =>
  parseSpaceSeparated(line).map(parseDecimalInt);

// ----

function Main(input: string): void {
  const lines = parseLines(input);
  const [t, a] = parseSpaceSeparatedDecimalInt(lines[1]);
  const h = parseSpaceSeparatedDecimalInt(lines[2]);

  const temperatureArray = h.map(h => t - h * 0.006);
  const len = temperatureArray.length;
  let minDistance = Infinity;
  let index = -1;

  for (let i = 0; i < len; i += 1) {
    const distance = Math.abs(temperatureArray[i] - a);

    if (distance > minDistance) continue;

    minDistance = distance;
    index = i;
  }

  log(index + 1);
}

Main(require("fs").readFileSync("/dev/stdin", "utf8"));


const input=require('fs').readFileSync('/dev/stdin','utf8').split(/[\s]/);const tn=():number=>{const a=input[0];input.shift();return Number(a)};const tnn=(n:number):number[]=>{const a=[];for(let i=0;i<n;i++){a.push(tn())}return a};const ts=():string=>{const a=input[0];input.shift();return String(a)};const tss=(n:number):string[]=>{const a=[];for(let i=0;i<n;i++){a.push(ts())}return a};const tc=():string=>{let a=input[0].split('');const b=a[0];a.shift();if(a.length>0){input[0]=a.join('')}else{input.shift()}return String(b)};const tcc=(n:number):string[]=>{const a=[];for(let i=0;i<n;i++){a.push(tc())}return a};const to=(...arg)=>{console.log(...arg)};const abs=(a)=>{return Math.abs(a)};const min=(...a)=>{return Math.min(...a)};const max=(...a)=>{return Math.max(...a)};const floor=(a)=>{return Math.floor(a)};const asc=(ar:number[])=>{return ar.sort((a,b)=>{return a-b})};const desc=(ar:number[])=>{return ar.sort((a,b)=>{return b-a})};const sw=(a,arr:any[],op:'=='|'>='|'>'|'<='|'<'='==')=>{for(let i=0;i<arr.length;i+=2){if(eval(a+op+arr[i]))return arr[i+1];}return arr[arr.length-1]};const near=(n:number,arr:number[]):number=>{let ne=arr[0],ni=0;for(let i=1;i<arr.length;i++){if(Math.abs(n-ne)>Math.abs(n-arr[i])){ne=arr[i];ni=i}}return ni};
const main=()=>{
  let [n,t,a]=tnn(3)
  let h=tnn(n)
  let arr=[]
  for(let i=0;i<n;i++){
    to(t-h[i]*0.006)
    arr.push(t-h[i]*0.006)
  }
  to(near(a,arr)+1)
}
main()


'use strict'
function Main(input) {
  const ar = input.split("\n").map(x => x.split(" "));
  const N = ar[0][0];
  const [T, A] = ar[1];
  const H = ar[2];

  const a = [];

  for (let i = 0; i < H.length; i++) {
    a.push([i, Math.abs(T * 1000 - H[i] * 6 - A * 1000)]);
  }

  console.log(a.reduce((x, y) => x[1] < y[1] ? x : y)[0] + 1);


L = int(input())

print(L**3 / 27)


n = int(input())
n = n/3
print(n**3)


l = int(input())
a = l/3
ans = a**3
print(round(ans,13))


import math,string,itertools,fractions,heapq,collections,re,array,bisect,sys,random,time, copy,bisect
from operator import itemgetter
#from heapq import heappush, heappop
#import numpy as np
#from scipy.sparse.csgraph import shortest_path, floyd_warshall, dijkstra, bellman_ford, johnson
#from scipy.sparse import csr_matrix
#from decimal import Decimal, ROUND_HALF_UP, ROUND_HALF_EVEN
sys.setrecursionlimit(10**7)
inf = 10**20
mod = 10**9 + 7

stdin = sys.stdin

ni = lambda: int(ns())
nf = lambda: float(ns())
na = lambda: list(map(int, stdin.readline().split()))
nb = lambda: list(map(float, stdin.readline().split()))
ns = lambda: stdin.readline().rstrip()  # ignore trailing spaces

L = ni()
ans = -1
for x in range(1, L+1):
    for y in range(x, L-x+1):
        z = L - x - y
        ans = max(ans, x*y*z)
print(ans)


n=int(input())
ans=[]

for B in range(1,n+1):
  for C in range(1,n+1):
    new_high=(n-(B+C))*B*C
    ans.append(new_high)

print(max(ans))


l = int(input())

v_max = 0
for width in range(1, l+1):
    for length in range(1, l+1):
        height = l - width - length
        v = width * height * length
        if v_max < v:
            v_max = v

print(v_max)


/*
If you want to aim high, aim high
Don't let that studying and grades consume you
Just live life young
******************************
If I'm the sun, you're the moon
Because when I go up, you go down
*******************************
I'm working for the day I will surpass you
https://www.a2oj.com/Ladder16.html
*/
import java.util.*;
import java.io.*;
import java.math.*;

   public class Main
   {
      public static void main(String omkar[]) throws Exception
      {
         BufferedReader infile = new BufferedReader(new InputStreamReader(System.in));
         StringTokenizer st = new StringTokenizer(infile.readLine());
         int N = Integer.parseInt(st.nextToken());
         double lol = 1.0*N;
         lol /= 3;
         System.out.println(lol*lol*lol);
      }
   }


import java.util.*;
import java.io.*;
import java.text.*;

public class Main {
    public static void main(String[] args) throws Exception {
        FastScanner sc = new FastScanner();
        int sum = sc.nextInt();
        double r = sum;
        r /=3;
        double v = r*r*r;
        System.out.println(v);
    }
}

class FastScanner {
    private final InputStream in = System.in;
    private final byte[] buffer = new byte[1024];
    private int ptr = 0;
    private int buflen = 0;
    private boolean hasNextByte() {
        if (ptr < buflen) {
            return true;
        }else{
            ptr = 0;
            try {
                buflen = in.read(buffer);
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (buflen <= 0) {
                return false;
            }
        }
        return true;
    }

    private int readByte() { if (hasNextByte()) return buffer[ptr++]; else return -1;}
    private static boolean isPrintableChar(int c) { return 33 <= c && c <= 126;}
    public boolean hasNext() { while(hasNextByte() && !isPrintableChar(buffer[ptr])) ptr++; return hasNextByte();}
    public String next() {
        if (!hasNext()) throw new NoSuchElementException();
        StringBuilder sb = new StringBuilder();
        int b = readByte();
        while(isPrintableChar(b)) {
            sb.appendCodePoint(b);
            b = readByte();
        }
        return sb.toString();
    }
    public long nextLong() {
        if (!hasNext()) throw new NoSuchElementException();
        long n = 0;
        boolean minus = false;
        int b = readByte();
        if (b == '-') {
            minus = true;
            b = readByte();
        }
        if (b < '0' || '9' < b) {
            throw new NumberFormatException();
        }
        while(true){
            if ('0' <= b && b <= '9') {
                n *= 10;
                n += b - '0';
            }else if(b == -1 || !isPrintableChar(b)){
                return minus ? -n : n;
            }else{
                throw new NumberFormatException();
            }
            b = readByte();
        }
    }
    public int nextInt() {
        long nl = nextLong();
        if (nl < Integer.MIN_VALUE || nl > Integer.MAX_VALUE) throw new NumberFormatException();
        return (int) nl;
    }
    public double nextDouble() { return Double.parseDouble(next());}
}


import java.io.*;import java.util.*;import java.math.*;
public class Main
{
	static long mod=1000000007l;
    static int max=Integer.MAX_VALUE,min=Integer.MIN_VALUE;
    static long maxl=Long.MAX_VALUE,minl=Long.MIN_VALUE;
    static BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;

    static public void main(String[] args)throws Exception
    {
    	st=new StringTokenizer(br.readLine());

    	double d=1.0*d();
    	d/=3;
    	pl(d*d*d);
    }
    static boolean f(String s)
    {
    	int k=s.length();
    	for(int x=0;x<k;x++)
    	{
    		if(s.charAt(x)!=s.charAt(s.length()-x-1))return false;
    	}
    	return true;
    }

    static int max(int a,int b){return Math.max(a,b);}
    static int min(int a,int b){return Math.min(a,b);}
    static int abs(int a){return Math.abs(a);}
    static long max(long a,long b){return Math.max(a,b);}
    static long min(long a,long b){return Math.min(a,b);}
    static long abs(long a){return Math.abs(a);}
    static int sq(int a){return (int)Math.sqrt(a);}
    static long sq(long a){return (long)Math.sqrt(a);}
    static int gcd(int a,int b) {return b==0?a:gcd(b,a%b);}
    static int ncr(int n,int c,long m)
    {
        long a=1l;
        for(int x=n-c+1;x<=n;x++)a=((a*x)%m);
        long b=1l;
        for(int x=2;x<=c;x++)b=((b*x)%m);
        long v=(div((int)b,m-2,m)%m);
        return (int)((a*v)%m);
    }
    static int fib(int n)
    {
        double p=(1+Math.sqrt(5))/2;
        return (int)Math.round(Math.pow(p,n)/Math.sqrt(5));
    }
    static boolean[] sieve(int n)
    {
        boolean bo[]=new boolean[n+1];
        bo[0]=true;bo[1]=true;
        for(int x=4;x<=n;x+=2)bo[x]=true;
        for(int x=3;x*x<=n;x+=2)
        {
            if(!bo[x])
            {
                for(int y=x*x;y<=n;y+=x)bo[y]=true;
            }
        }
        return bo;
    }
    static int[] fac(int n)
    {
        int bo[]=new int[n+1];
        bo[0]=0;bo[1]=1;
        for(int x=1;x<=n;x++)
        {
            for(int y=x;y<=n;y+=x)bo[y]++;
        }
        return bo;
    }
    static long div(long a,long b,long m)
    {
        long r=1l;
        a%=m;
        while(b>0)
        {
            if((b&1)==1)r=(r*a)%m;
            b>>=1;
            a=(a*a)%m;
        }
        return r;
    }
    static int i()throws IOException
    {
        if(!st.hasMoreTokens()) st=new StringTokenizer(br.readLine());
        return Integer.parseInt(st.nextToken());
    }
    static long l()throws IOException
    {
        if(!st.hasMoreTokens())st=new StringTokenizer(br.readLine());
        return Long.parseLong(st.nextToken());
    }
    static String s()throws IOException
    {
        if(!st.hasMoreTokens())st=new StringTokenizer(br.readLine());
        return st.nextToken();
    }
    static double d()throws IOException
    {
        if(!st.hasMoreTokens())st=new StringTokenizer(br.readLine());
        return Double.parseDouble(st.nextToken());
    }
    static void p(Object p){System.out.print(p);}
    static void p(String p){System.out.print(p);}
    static void p(int p){System.out.print(p);}
    static void p(double p){System.out.print(p);}
    static void p(long p){System.out.print(p);}
    static void p(char p){System.out.print(p);}
    static void p(boolean p){System.out.print(p);}
    static void pl(Object p){System.out.println(p);}
    static void pl(String p){System.out.println(p);}
    static void pl(int p){System.out.println(p);}
    static void pl(char p){System.out.println(p);}
    static void pl(double p){System.out.println(p);}
    static void pl(long p){System.out.println(p);}
    static void pl(boolean p){System.out.println(p);}
    static void pl(){System.out.println();}
    static int[] ari(int n)throws IOException
    {
        int ar[]=new int[n];
        st=new StringTokenizer(br.readLine());
        for(int x=0;x<n;x++) ar[x]=Integer.parseInt(st.nextToken());
        return ar;
    }
    static int[][] ari(int n,int m)throws IOException
    {
        int ar[][]=new int[n][m];
        for(int x=0;x<n;x++)
        {
            st=new StringTokenizer(br.readLine());
            for(int y=0;y<m;y++)ar[x][y]=Integer.parseInt(st.nextToken());
        }
        return ar;
    }
    static long[] arl(int n)throws IOException
    {
        long ar[]=new long[n];
        st=new StringTokenizer(br.readLine());
        for(int x=0;x<n;x++) ar[x]=Long.parseLong(st.nextToken());
        return ar;
    }
    static long[][] arl(int n,int m)throws IOException
    {
        long ar[][]=new long[n][m];
        for(int x=0;x<n;x++)
        {
            st=new StringTokenizer(br.readLine());
            for(int y=0;y<m;y++)ar[x][y]=Long.parseLong(st.nextToken());
        }
        return ar;
    }
    static String[] ars(int n)throws IOException
    {
        String ar[]=new String[n];
        st=new StringTokenizer(br.readLine());
        for(int x=0;x<n;x++) ar[x]=st.nextToken();
        return ar;
    }
    static double[] ard(int n)throws IOException
    {
        double ar[]=new double[n];
        st=new StringTokenizer(br.readLine());
        for(int x=0;x<n;x++)ar[x]=Double.parseDouble(st.nextToken());
        return ar;
    }
    static double[][] ard(int n,int m)throws IOException
    {
        double ar[][]=new double[n][m];
        for(int x=0;x<n;x++)
        {
            st=new StringTokenizer(br.readLine());
            for(int y=0;y<m;y++)ar[x][y]=Double.parseDouble(st.nextToken());
        }
        return ar;
    }
    static char[] arc(int n)throws IOException
    {
        char ar[]=new char[n];
        st=new StringTokenizer(br.readLine());
        for(int x=0;x<n;x++)ar[x]=st.nextToken().charAt(0);
        return ar;
    }
    static char[][] arc(int n,int m)throws IOException
    {
        char ar[][]=new char[n][m];
        for(int x=0;x<n;x++)
        {
            String s=br.readLine();
            for(int y=0;y<m;y++)ar[x][y]=s.charAt(y);
        }
        return ar;
    }
    static void p(int ar[])
    {
        StringBuilder sb=new StringBuilder("");;
        for(int a:ar) sb.append(a+" ");
        System.out.println(sb);
    }
    static void p(int ar[][])
    {
        StringBuilder sb;
        for(int a[]:ar)
        {
            sb=new StringBuilder("");
            for(int aa:a) sb.append(aa+" ");
            System.out.println(sb);
        }
    }
    static void p(long ar[])
    {
        StringBuilder sb=new StringBuilder("");
        for(long a:ar)sb.append(a+" ");
        System.out.println(sb);
    }
    static void p(long ar[][])
    {
        StringBuilder sb;
        for(long a[]:ar)
        {
            sb=new StringBuilder("");
            for(long aa:a)sb.append(aa+" ");
            System.out.println(sb);
        }
    }
    static void p(String ar[])
    {
        StringBuilder sb=new StringBuilder("");
        for(String a:ar)sb.append(a+" ");
        System.out.println(sb);
    }
    static void p(double ar[])
    {
        StringBuilder sb=new StringBuilder("");
        for(double a:ar)sb.append(a+" ");
        System.out.println(sb);
    }
    static void p(double ar[][])
    {
        StringBuilder sb;
        for(double a[]:ar)
        {
            sb=new StringBuilder("");
            for(double aa:a)sb.append(aa+" ");
            System.out.println(sb);
        }
    }
    static void p(char ar[])
    {
        StringBuilder sb=new StringBuilder("");
        for(char aa:ar)sb.append(aa+" ");
        System.out.println(sb);
    }
    static void p(char ar[][])
    {
        StringBuilder sb;
        for(char a[]:ar)
        {
            sb=new StringBuilder("");
            for(char aa:a)sb.append(aa+" ");
            System.out.println(sb);
        }
    }
}


import java.math.BigDecimal;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        BigDecimal ll = sc.nextBigDecimal();
        BigDecimal ans2 = ll.divide(new BigDecimal(3.0));
        BigDecimal ans3 = ans2.multiply(ans2);
        BigDecimal ans4 = ans3.multiply(ans2);
        System.out.println(ans4);
    }
}


import java.math.BigDecimal;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        BigDecimal ll = sc.nextBigDecimal();
        BigDecimal ans2 = ll.divide(new BigDecimal(3.0));
        BigDecimal ans3 = ans2.multiply(ans2).multiply(ans2);
        System.out.println(ans3);
    }
}


import java.math.BigDecimal;
import java.util.Scanner;

public class Main {

  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    int l = sc.nextInt();
    sc.close();
    BigDecimal input = new BigDecimal(l);
    BigDecimal a = input.divide(new BigDecimal(3));
    BigDecimal ans = a.multiply(a).multiply(a);
    System.out.println(ans.toString());
  }
}


#include<bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define ll long long
#define mod 1000000007
using namespace std;
ll gcd(ll a, ll b)
{
    if (b == 0)
        return a;
    return gcd(b, a % b);

}
int main()
{
    ios_base:: sync_with_stdio(false);
	cin.tie(NULL); cout.tie(NULL);
    double n;
    cin>>n;
    double a = n/3;
    a = a*a*a;
    cout<<fixed<<setprecision(9)<<a;
}


/**
 *  author: mahfuzz
 *  created: 22.03.2020
**/

#include <bits/stdc++.h>
using namespace std;
#define debug(x) cout << #x << ':' << x << "\n";
//~ const double pi = 2*acos(0.0);
//~ const long long mod = 1e9+7;
//~ const int max_n = 1e6+5;
typedef long long ll;

int main(int argc, char* argv[]){
    ios_base::sync_with_stdio(0);
    cin.tie(NULL);

    double l; cin >> l;

    double a = l / 3.;

    cout << fixed << setprecision(12) << a * a * a << "\n";

    return 0;
}


#include<bits/stdc++.h>
using namespace std;

int main(){
  double l;cin>>l;
  double lm=l/3;

  cout<<fixed<<setprecision(12);
  cout<<lm*lm*lm<<endl;
}


#include<bits/stdc++.h>
using namespace std;
#define ll long  long int

int main()
{

    ll n;
    cin>>n;
    long double d=(double)(n*n*n)/3;
    string s=to_string(d);
    for(int i=0;i<6;i++)
    {
        s+='0';
    }
    cout<<s<<endl;

    return 0;
}


#include <iostream>
#include <cmath>
#include <iomanip>

using namespace std;
int main() {
    double sum;
    cin >> sum;
    cout << fixed;
    cout << setprecision(12);
    if(sum == 1) cout << pow(1.0,3) << endl;
    else
        cout << pow(sum/3, 3) << endl;

}


// C - Mazimum Volume
#include <bits/stdc++.h>
#define rep(i, n) for(int i=0; i<(int)(n); i++)
using namespace std;
using ll = long long;
using ull = unsigned long long;

int main(){
    int l;
    cin >> l;
    double ans = 1.0;
    if(l%3 == 0) ans = l/3*l/3*l/3;
    else if(l%3 == 1){
        int l2 = l/3+1;
        ans = l/3*l/3*l2;
    }
    else{
        int l2 = l/3+1;
        ans = l/3*l2*l2;
    }
    printf("%.20f\n", ans);
    return 0;
}


#include <stdio.h>

int main()
{
int X;
scanf("%d",&X);
printf("%.12f\n",(double)X*X*X/27);
}


#include <stdio.h>
#include<string.h>
int main()
{
    double l;
    scanf("%lf",&l);
    printf("%lf",(l/3.0)*(l/3.0)*(l/3.0));
}


#include <stdio.h>

int main()
{
	double a;
  double b;
  double result;
	scanf("%lf", &a);
  b = a/3.0000000000;
  result = b*b*b;

  printf("%.10f", result);
    return 0;
}


#include<stdio.h>
int main ()
{
    double x,y;
    int l;
    scanf("%d", &l);
    y=l/3;
    x=y*y*y;
    printf("%.12lf\n", x);
}


#include<stdio.h>
int main ()
{
    double x;
    int l;
    scanf("%d", &l);
    x=(l/3*l/3*l/3);
    printf("%.12lf\n", x);
}


#include<stdio.h>
int main ()
{
    double x;
    int l;
    scanf("%d", &l);
    if(l%3==0){x=(l/3*l/3*l/3);}
    else if(l%3==1){x=(l/3*(l/3)*(l/3+1));}
    else if(l%3==2){x=(l/3*(l/3+1)*(l/3+1));}
    printf("%.12lf\n", x);
}


function Main(input) {
	var str = input;
	var ans = 0;
	str = str.split("\n");
	var l = Number(str[0].split(" ")[0]);
 	var n = (l / 3).toFixed(6);
 	var ans = (n**3).toFixed(6);
 	console.log(ans);
}
 //*おまじない
Main(require("fs").readFileSync("/dev/stdin", "utf8"));


function Main(input) {
  lines = input.split("\n");
  var volume=lines[0]*lines[0]*lines[0]/27;
  console.log(volume);
}
Main(require("fs").readFileSync("/dev/stdin", "utf8"));


// inputに入力データ全体が入る
function Main(input) {
	// 1行目がinput[0], 2行目がinput[1], …に入る
	input = input.split("\n");
    res = Math.pow(parseInt(input[0])/3,3);
	console.log(res);
}
//*この行以降は編集しないでください（標準入出力から一度に読み込み、Mainを呼び出します）
Main(require("fs").readFileSync("/dev/stdin", "utf8"));


"use strict";

const main = arg => {

    const L = parseInt(arg.trim())

    let max_volume = 0;

    for (let i = 1; i <= L; i++) {
        for (let j = i; i + j <= L; j++) {
            for (let k = j; i + j + k <= L; k++) {
                max_volume = Math.max(max_volume, i * j * k);
            }
        }
    }

    console.log(max_volume);

}

main(requre('fs').readFileSync('/dev/stdin', 'utf8'));


function Main(input) {
  input = input.split("\n");
  intInput = parseInt(input)
  var volume=(input)*(input)*(input)/27;
  console.log(volume.toFixed(12));
}
Main(require("fs").readFileSync("/dev/stdin", "utf8"));


function Main(input) {
  input = input.split("\n");
  intInput = parseInt(input);
  var volume=(input/3)*(input/3)*(input/3);
  console.log(volume.toFixed(12));
}
Main(require("fs").readFileSync("/dev/stdin", "utf8"));


package main

import (
	"fmt"
	"strconv"
)

func main() {
	var n float64
	fmt.Scan(&n)
	a := (n / 3.0)
	b := (a * a * a)
	fmt.Println(strconv.FormatFloat(b, 'f', 12, 64))
}


package main

import (
	"fmt"
	"strconv"
)

func main() {
	var n float64
	fmt.Scan(&n)
	a := (n / 3.0) * 100000
	b := (a * a * a) / (100000 * 100000 * 100000)
	fmt.Println(strconv.FormatFloat(b, 'f', 12, 64))
}


package main

import "fmt"

func main() {
	var L int
	fmt.Scanf("%d", &L)

	var ans float64
	ans = float64(L*L*L) / 27

	fmt.Printf("%f\n", ans)
}


package main

import (
	"fmt"
)

func main() {

	var L int
	fmt.Scanf("%d", &L)

	var max, volume int
	max = 0
	for i := 1; i <= 1000; i++ {
		for j := 1; j <= 1000; j++ {
			for k := 1; k <= 1000; k++ {
				if i+j+k == L {
					volume = i * k * j
					if volume > max {
						max = volume
					}
				}
			}
		}
	}

	fmt.Println(max)
}


package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strconv"
)

const mod = 998244353
const facNum = 300001

func main() {
	sc := newScanner(os.Stdin)
	L := sc.i()
	ans := float64(Pow(L, 3)) / 27
	fmt.Printf("%.10f", ans)
}

// fmt.Println("Yes")
// fmt.Println("No")

// I/O
type scanner struct {
	sc *bufio.Scanner
}

func newScanner(input io.Reader) *scanner {
	sc := bufio.NewScanner(input)
	sc.Split(bufio.ScanWords)
	sc.Buffer(make([]byte, 1024), int(1e+9))
	return &scanner{sc}
}

func (s *scanner) s() string {
	s.sc.Scan()
	return s.sc.Text()
}

func (s *scanner) i() int {
	i, e := strconv.Atoi(s.s())
	if e != nil {
		panic(e)
	}
	return i
}

func (s *scanner) f() float64 {
	f, e := strconv.ParseFloat(s.s(), 64)
	if e != nil {
		panic(e)
	}
	return f
}

func (s *scanner) bs() []byte {
	return []byte(s.s())
}

func (s *scanner) is(n int) []int {
	res := make([]int, n)
	for i := 0; i < n; i++ {
		res[i] = s.i()
	}
	return res
}

func (s *scanner) fs(n int) []float64 {
	res := make([]float64, n)
	for i := 0; i < n; i++ {
		res[i] = s.f()
	}
	return res
}

//------------------------------

//const factorial = new
func Pow(a, n int) int {
	ans := 1
	for n > 0 {
		if (n & 1) == 1 {
			ans = ans * a % mod
		}
		a = a * a % mod
		n = n >> 1
	}
	return ans
}

// a^{-1} (mod) を計算
func Inv(a int) int {
	return Pow(a, mod-2)
}

func Gcd(a, b int) int {
	if a < b {
		return Gcd(b, a)
	}
	for b != 0 {
		a, b = b, a%b
	}
	return a
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func combination(n, k int, fac, ifac []int) int {
	if n < k || n < 0 {
		return 0
	}
	if k == 0 {
		return 1
	}
	//while n != 0
	ans := ifac[k] * ifac[n-k] % mod
	return ans * fac[n] % mod
}

func abs(i int) int {
	if i < 0 {
		return -i
	}
	return i
}

// 階乗: factorial
// コンビネーションを計算する際に前もって計算しておく
// fac[k] => k! (mod M)
// ifac[k] => k!^(M-2) (mod M)
// n: ex. 2 * 10^5 => 200001
// fac, ifac := factorial()
func factorial() (fac []int, ifac []int) {
	fac = make([]int, facNum)
	fac[0] = 1
	ifac = make([]int, facNum)
	ifac[0] = 1
	for i := 1; i < facNum; i++ {
		fac[i] = fac[i-1] * i % mod
		ifac[i] = ifac[i-1] * Pow(i, mod-2) % mod
	}
	return
}

// vs: sorted slice int value
func lowerBound(vs []int, v int) (index int) {
	n := len(vs) / 2
	m := len(vs)
	for m != n {
		if vs[n] < v {
			n = (m-n+1)/2 + n
			//m = m
		} else {
			m = n
			n = n / 2
		}
	}
	return n
}

func IntSlice(n, init int) []int {
	r := make([]int, n)
	for i := range r {
		r[i] = init
	}
	return r
}


package main

import (
	"fmt"
)

var N float64
func main() {
	fmt.Scan(&N)
	a := N / 3
	b := N / 3
	//fmt.Printf("%v\n%v\n%v\n", a, b, N - a -b)
	fmt.Println(int(a) * int(b) * int(N - a - b))
}
func calmax(a, b int) int {
	if a > b {
		return a
	}
	return b
}


puts (gets.to_f/3)**3


l = gets.chomp.to_r
a = l/3

v = a * a * a

puts "%.7f" % v


l = gets.to_f/3
puts l**3


n=gets.to_i
puts format("%.12f",((n**3)/27))


n=gets.to_i
format("%.12f",((n**3)/27))


fn main() {
    let l = read::<f64>();
    let a = l / 3.0;
    println!("{}", a*a*a);
}

fn read<T: std::str::FromStr>() -> T {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).unwrap();
    s.trim().parse().ok().unwrap()
}


macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_whitespace();
        let mut next = || { iter.next().unwrap() };
        input_inner!{next, $($r)*}
    };
    ($($r:tt)*) => {
        let stdin = std::io::stdin();
        let mut bytes = std::io::Read::bytes(std::io::BufReader::new(stdin.lock()));
        let mut next = move || -> String{
            bytes
                .by_ref()
                .map(|r|r.unwrap() as char)
                .skip_while(|c|c.is_whitespace())
                .take_while(|c|!c.is_whitespace())
                .collect()
        };
        input_inner!{next, $($r)*}
    };
}

macro_rules! input_inner {
    ($next:expr) => {};
    ($next:expr, ) => {};

    ($next:expr, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($next, $t);
        input_inner!{$next $($r)*}
    };
}

macro_rules! read_value {
    ($next:expr, ( $($t:tt),* )) => {
        ( $(read_value!($next, $t)),* )
    };

    ($next:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($next, $t)).collect::<Vec<_>>()
    };

    ($next:expr, Chars) => {
        read_value!($next, String).chars().collect::<Vec<char>>()
    };

    ($next:expr, usize1) => {
        read_value!($next, usize) - 1
    };

    ($next:expr, $t:ty) => {
        $next().parse::<$t>().expect("Parse error")
    };
}

fn main() {
    input! {
        l: f64,
    }

    let len = l / 3.0;
    println!("{:.12}", len.powf(3.0));
}


/* {{{ */
macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
    ($($r:tt)*) => {
        let s = {
            use std::io::Read;
            let mut s = String::new();
            std::io::stdin().read_to_string(&mut s).unwrap();
            s
        };
        let mut iter = s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
}

macro_rules! input_inner {
    ($iter:expr) => {};
    ($iter:expr, ) => {};
    ($iter:expr, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($iter, $t);
        input_inner!{$iter $($r)*}
    };
}

macro_rules! read_value {
    ($iter:expr, ( $($t:tt),* )) => {
        ( $(read_value!($iter, $t)),* )
    };
    ($iter:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($iter, $t)).collect::<Vec<_>>()
    };
    ($iter:expr, chars) => {
        read_value!($iter, String).chars().collect::<Vec<char>>()
    };
    ($iter:expr, usize1) => {
        read_value!($iter, usize) - 1
    };
    ($iter:expr, $t:ty) => {
        $iter.next().unwrap().parse::<$t>().expect("Parse error")
    };
}
/* }}} */

fn main() {
    input! {
        l: f64
    }
    let r = l / 3.0;
    println!("{}", r*r*r);
}
/* vim:set foldmethod=marker: */


#[warn(unused_imports)]
use proconio::{fastout, input, marker::*};

#[fastout]
fn main() {
    input! {
        l: usize,
    }

    let mut ans = 0f64;
    let l = l * 10;

    for x in 0..l+1 {
        for y in 0..l-x+1 {
            let z = (l - x - y) as f64 / 10.0;
            let x = x as f64 / 10.0;
            let y = y as f64 / 10.0;
            ans = ans.max(x * y * z);
        }
    }

    println!("{}", ans);
}


use proconio::input;

fn main() {
    input!{
        l: i32,
    }

    let a = l / 3;
    let ans = a * a * a;

    println!("{}", ans);
}


use proconio::{fastout, input};

#[fastout]
fn main() {
    input! {l: usize};

    let x = l % 3;

    let v = if x == 2 {
        l / 3 * (l / 3 + 1) * (l / 3 + 1)
    } else if x == 1 {
        l / 3 * l / 3 * (l / 3 + 1)
    } else {
        l / 3 * l / 3 * l / 3
    };

    println!("{}", v);
}


import Foundation
let N = Double(String(readLine()!))!
print(N * N * N / 27.0)


let l = Double(readLine()!)!
let edge = l/3.0
print(edge*edge*edge)


import Foundation

/*
// 1
let N = Int(readLine()!)!

// 1 2
let split = readLine()!.componentsSeparatedByString(" ")
let N = Int(split[0])!
let S = Int(split[1])!

// 1 2 3 4 5
let array = readLine()!.componentsSeparatedByString(" ").map { Int($0)! }
*/

let N = Double(readLine()!)!
print((N / 3) * (N / 3) * (N / 3))


import Foundation
let N = Int(String(readLine()!))!
print(Double(N * N * N / 27))


import Foundation
let str = String(readLine()!)
let L = Int(str)!

let width = Double(L / 3)
let height = width
let depth = width

print(width * height * depth)


import Foundation
let str = String(readLine()!)
let L = Int(str)!

let width = L / 3
let height = width
let depth =  L / 3 + (L - width * 3)

print(Double(width * height * depth))


import * as fs from 'fs';
const input = fs.readFileSync("/dev/stdin", "utf8");

const L = +input;

const taiseki = (L / 3) * (L / 3) * (L / 3);

console.log(taiseki);


import * as fs from "fs";

const input = (fs.readFileSync("/dev/stdin", "utf8") as string).split("\n");
const l = +input[0];

console.log(Math.pow(l/3,3).toFixed(6));


function Main(input: string) {
  const val = (+input /3 );
  console.log(val * val * val)
}

Main(require("fs").readFileSync("/dev/stdin", "utf8"));


import * as fs from 'fs';

// main
function main(input: string[]) {
    // param
    var n: number = 0;
    var m: number = 0;
    var ans: number = 0;
    // init
    [n, m] = input.shift().split(" ").map(x => Number(x));
    // solve
    ans = n * (n - 1) / 2 + m * (m - 1) / 2
    // answer
    console.log(ans);
}
// entrypoint
function entrypoint() {
    try {
        // linux
        var input = fs.readFileSync("/dev/stdin", "utf8").trim().split("\n");
        console.debug = function () { };
        main(input);
    }
    catch (ex) {
        // windows
        const lines: string[] = [];
        // @ts-ignore
        const reader = require('readline').createInterface({
            // @ts-ignore
            input: process.stdin,
            // @ts-ignore
            output: process.stdout
        });
        reader.on('line', function (line: string) {
            lines.push(line);
        });
        reader.on('close', function () {
            input = lines;
            main(input);
        });
    }
}
entrypoint();


import * as fs from 'fs';

namespace AtCoder.abc159 {

    class ProgramC {
        args: string[];

        constructor(args: string[]) {
            this.args = args;
        }

        /**
         * in
         * 999
         * out
         *
         */
        main(): void {
            const l: number = parseInt(this.args[0]);

            let a: number = 0;
            let b: number = 0;
            let c: number = 0;

            a = Math.ceil(l / 3);
            b = Math.ceil(l / 3);
            c = l - (a + b);

            console.log(a*b*c);
        }
    }

    const args = fs.readFileSync('/dev/stdin', 'utf8').trim().split('\n');
    const prg = new ProgramC(args);
    prg.main();
}


const stdin: string[] = [];

function main() {
    const input = stdin[0];
    const L = parseInt(input, 10);

    const N = L / 3;
    const n = Math.floor(N);
    const d = N - n;
    let A = 0;
    let B = 0;
    if (d > 0.5) {
        A += 1;
        B += 1;
    } else if (d > 0.1) {
        A += 1;
    }
    console.log(N * (N+A) * (N+B));
}

require("readline").createInterface({
  input: process.stdin,
  output: process.stdout
}).on("line", _ => {
    stdin.push(_);
}).on("close", () => main());


import sys
input()
ans,d=0,{}
for ln in sys.stdin:
    s=''.join(sorted(ln))
    ans+=d.setdefault(s,0)
    d[s]+=1
print(ans)


import sys
input()
ans,c=0,{}
for ln in sys.stdin:
    s=''.join(sorted(ln))
    ans+=c.setdefault(s,0)
    c[s]+=1
print(ans)


from collections import Counter
import itertools
n = int(input())
l = []
for i in range(n):
    s = input()
    l.append(Counter(s))

q = list(itertools.combinations(range(n), 2))
ans = 0

for i in range(len(q)):
    if l[q[i][0]] == l[q[i][1]]:
        ans += 1

print(ans)


def resolve():
    n = int(input())
    words = []
    for _ in range(n):
        words.append(str(sorted(list(input()))))
    a = collections.Counter(words)
    ans = 0
    for i in a.values():
        ans += i*(i-1)//2
    print(ans)
resolve()


from collections import Counter
N = int(input())
S = [input() for _ in range(N)]
S_counter = Counter(S)
ans = 0
for i in S_counter.values():
    if i > 1:
        ans += (i-1)*i/2
print(int(ans))


import java.util.*;
import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Main {
    public static void main(String[] args) throws Exception {
        BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));

        Long count = new Long(0);

        Integer n = Integer.parseInt(stdin.readLine());

        Map<String, Integer> map = new HashMap<>();

        // 標準入力を1行ずつ読み出す。
        String line;
        while ((line = stdin.readLine()) != null) {
            char[] chars = line.toCharArray();
            Arrays.sort(chars);
            String newStr = new String(chars);
            Integer temp = map.get(newStr);
            if (temp == null) {
                map.put(newStr, 1);
            } else {
                count += temp;
                map.put(newStr, temp+1);
            }
        }
        System.out.println(count);
    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.BufferedWriter;
import java.util.HashMap;
import java.util.InputMismatchException;
import java.io.IOException;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        OutputWriter out = new OutputWriter(outputStream);
        CGreenBin solver = new CGreenBin();
        solver.solve(1, in, out);
        out.close();
    }

    static class CGreenBin {
        static final long MOD = (long) (1e16 + 61);
        static final int base = 31;

        long getHash(String s) {
            int[] freq = new int[26];
            for (int i = 0; i < s.length(); i++) freq[s.charAt(i) - 'a']++;
            long h = 0;
            for (int i = 0; i < 26; i++) h = (h * base + freq[i]) % MOD;
            return h;
        }

        public void solve(int testNumber, InputReader in, OutputWriter out) {
            int n = in.nextInt();
            long ans = 0;
            HashMap<Long, Integer> hm = new HashMap<>();
            for (int i = 0; i < n; i++) {
                long h = getHash(in.next());
                int t;
                ans += (t = hm.containsKey(h) ? hm.get(h) : 0);
                hm.put(h, t + 1);
            }
            out.println(ans);
        }

    }

    static class OutputWriter {
        private final PrintWriter writer;

        public OutputWriter(OutputStream outputStream) {
            writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
        }

        public OutputWriter(Writer writer) {
            this.writer = new PrintWriter(writer);
        }

        public void println(Object... objects) {
            for (int i = 0; i < objects.length; i++) {
                if (i != 0) {
                    writer.print(' ');
                }
                writer.print(objects[i]);
            }
            writer.print('\n');
        }

        public void close() {
            writer.close();
        }

    }

    static class InputReader {
        private InputStream stream;
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;
        private InputReader.SpaceCharFilter filter;

        public InputReader(InputStream stream) {
            this.stream = stream;
        }

        public int read() {
            if (numChars == -1) {
                throw new InputMismatchException();
            }
            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = stream.read(buf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (numChars <= 0) {
                    return -1;
                }
            }
            return buf[curChar++];
        }

        public int nextInt() {
            int c = read();
            while (isSpaceChar(c)) c = read();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            int res = 0;
            do {
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public String next() {
            int c;
            while (isSpaceChar(c = this.read())) {
                ;
            }

            StringBuilder result = new StringBuilder();
            result.appendCodePoint(c);

            while (!isSpaceChar(c = this.read())) {
                result.appendCodePoint(c);
            }

            return result.toString();
        }

        public boolean isSpaceChar(int c) {
            if (filter != null) {
                return filter.isSpaceChar(c);
            }
            return isWhitespace(c);
        }

        public static boolean isWhitespace(int c) {
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

        public interface SpaceCharFilter {
            public boolean isSpaceChar(int ch);

        }

    }
}


import java.io.*;
import java.util.*;

public class Main {
	static void solve() {
		int n = ni();
		char s[][] = new char[n][10];
		Map<String, Integer> map = new HashMap<>();
		for(int i=0;i<n;i++) {
			s[i] = ns(10);
			sort(s[i]);
			String t = String.valueOf(s[i]);
			map.put(t, map.getOrDefault(t, 0)+1);
		}
		long ans = 0;
		for(long v:map.values()) {
			ans += v*(v-1)/2;
		}
		out.println(ans);

	}

	//constant
	static final long mod = (long) 1e9 + 7;
	static final int dx[] = { -1, 0, 1, 0 }, dy[] = { 0, -1, 0, 1 };
	static final int[] dx8 = { -1, -1, -1, 0, 0, 1, 1, 1 }, dy8 = { -1, 0, 1, -1, 1, -1, 0, 1 };
	static final int inf = Integer.MAX_VALUE / 2;
	static final long linf = Long.MAX_VALUE / 3;
	static final double dinf = Double.MAX_VALUE / 3;
	static final double eps = 1e-10;
	static final double pi = Math.PI;
	static StringBuilder sb = new StringBuilder();
	static InputStream is;
	static PrintWriter out;
	static String INPUT = "";

	//libraries
	static void reverse(int ar[]) {
		int len = ar.length;
		for (int i = 0; i < len / 2; i++) {
			int t = ar[i];
			ar[i] = ar[len - 1 - i];
			ar[len - 1 - i] = t;
		}
	}

	static void reverse(long ar[]) {
		int len = ar.length;
		for (int i = 0; i < len / 2; i++) {
			long t = ar[i];
			ar[i] = ar[len - 1 - i];
			ar[len - 1 - i] = t;
		}
	}

	static void reverse(double ar[]) {
		int len = ar.length;
		for (int i = 0; i < len / 2; i++) {
			double t = ar[i];
			ar[i] = ar[len - 1 - i];
			ar[len - 1 - i] = t;
		}
	}

	static void reverse(char ar[]) {
		int len = ar.length;
		for (int i = 0; i < len / 2; i++) {
			char t = ar[i];
			ar[i] = ar[len - 1 - i];
			ar[len - 1 - i] = t;
		}
	}

	static String getReverse(String s) {
		char c[] = s.toCharArray();
		reverse(c);
		s = String.valueOf(c);
		return s;
	}

	static <T> void reverse(List<T> ls) {
		int sz = ls.size();
		for (int i = 0; i < sz / 2; i++) {
			T t = ls.get(i);
			ls.set(i, ls.get(sz - 1 - i));
			ls.set(sz - 1 - i, t);
		}
	}

	static <T> void reverse(T[] ar) {
		int len = ar.length;
		for (int i = 0; i < len / 2; i++) {
			T t = ar[i];
			ar[i] = ar[len - 1 - i];
			ar[len - 1 - i] = t;
		}
	}

	static void sbnl() {//StringBuilderに改行文字をappendする
		sb.append("\n");
	}

	static int lowerBound(int[] a, int x) {
		int l = -1, r = a.length;
		while (r - l > 1) {
			int c = (l + r) / 2;
			if (a[c] < x) {
				l = c;
			} else {
				r = c;
			}
		}
		return r;
	}

	static int upperBound(int[] a, int x) {
		int l = -1, r = a.length;
		while (r - l > 1) {
			int c = (l + r) / 2;
			if (a[c] <= x) {
				l = c;
			} else {
				r = c;
			}
		}
		return r;
	}

	static int rlowerBound(int[] a, int x) {
		int l = -1, r = a.length;
		while (r - l > 1) {
			int c = (l + r) / 2;
			if (a[c] > x) {
				l = c;
			} else {
				r = c;
			}
		}
		return r;
	}

	static int rupperBound(int[] a, int x) {
		int l = -1, r = a.length;
		while (r - l > 1) {
			int c = (l + r) / 2;
			if (a[c] >= x) {
				l = c;
			} else {
				r = c;
			}
		}
		return r;
	}

	static int lowerBound(long[] a, long x) {
		int l = -1, r = a.length;
		while (r - l > 1) {
			int c = (l + r) / 2;
			if (a[c] < x) {
				l = c;
			} else {
				r = c;
			}
		}
		return r;
	}

	static int upperBound(long[] a, long x) {
		int l = -1, r = a.length;
		while (r - l > 1) {
			int c = (l + r) / 2;
			if (a[c] <= x) {
				l = c;
			} else {
				r = c;
			}
		}
		return r;
	}

	static int rlowerBound(long[] a, long x) {
		int l = -1, r = a.length;
		while (r - l > 1) {
			int c = (l + r) / 2;
			if (a[c] > x) {
				l = c;
			} else {
				r = c;
			}
		}
		return r;
	}

	static int rupperBound(long[] a, long x) {
		int l = -1, r = a.length;
		while (r - l > 1) {
			int c = (l + r) / 2;
			if (a[c] >= x) {
				l = c;
			} else {
				r = c;
			}
		}
		return r;
	}

	static int lowerBound(double[] a, double x) {
		int l = -1, r = a.length;
		while (r - l > 1) {
			int c = (l + r) / 2;
			if (a[c] < x) {
				l = c;
			} else {
				r = c;
			}
		}
		return r;
	}

	static int upperBound(double[] a, double x) {
		int l = -1, r = a.length;
		while (r - l > 1) {
			int c = (l + r) / 2;
			if (a[c] <= x) {
				l = c;
			} else {
				r = c;
			}
		}
		return r;
	}

	static int rlowerBound(double[] a, double x) {
		int l = -1, r = a.length;
		while (r - l > 1) {
			int c = (l + r) / 2;
			if (a[c] > x) {
				l = c;
			} else {
				r = c;
			}
		}
		return r;
	}

	static int rupperBound(double[] a, double x) {
		int l = -1, r = a.length;
		while (r - l > 1) {
			int c = (l + r) / 2;
			if (a[c] >= x) {
				l = c;
			} else {
				r = c;
			}
		}
		return r;
	}

	static int lowerBound(char[] a, char x) {
		int l = -1, r = a.length;
		while (r - l > 1) {
			int c = (l + r) / 2;
			if (a[c] < x) {
				l = c;
			} else {
				r = c;
			}
		}
		return r;
	}

	static int upperBound(char[] a, char x) {
		int l = -1, r = a.length;
		while (r - l > 1) {
			int c = (l + r) / 2;
			if (a[c] <= x) {
				l = c;
			} else {
				r = c;
			}
		}
		return r;
	}

	static int rlowerBound(char[] a, char x) {
		int l = -1, r = a.length;
		while (r - l > 1) {
			int c = (l + r) / 2;
			if (a[c] > x) {
				l = c;
			} else {
				r = c;
			}
		}
		return r;
	}

	static int rupperBound(char[] a, char x) {
		int l = -1, r = a.length;
		while (r - l > 1) {
			int c = (l + r) / 2;
			if (a[c] >= x) {
				l = c;
			} else {
				r = c;
			}
		}
		return r;
	}

	static <T> int lowerBound(List<T> ls, T x) throws RuntimeException {
		if (ls.size() == 0)
			return -1;
		if (ls.get(0) instanceof Integer) {
			return ~Collections.binarySearch(ls, x, (t1, t2) -> ((Integer) t1).compareTo((Integer) t2) >= 0 ? 1 : -1);
		} else if (ls.get(0) instanceof Long) {
			return ~Collections.binarySearch(ls, x, (t1, t2) -> ((Long) t1).compareTo((Long) t2) >= 0 ? 1 : -1);
		} else if (ls.get(0) instanceof Double) {
			return ~Collections.binarySearch(ls, x, (t1, t2) -> ((Double) t1).compareTo((Double) t2) >= 0 ? 1 : -1);
		} else {
			System.err.println(
					String.format("%s:数値でないリストを二分探索しています。", Thread.currentThread().getStackTrace()[1].getMethodName()));
			throw new RuntimeException();
		}
	}

	static <T> int upperBound(List<T> ls, T x) throws RuntimeException {
		if (ls.size() == 0)
			return -1;
		if (ls.get(0) instanceof Integer) {
			return ~Collections.binarySearch(ls, x, (t1, t2) -> ((Integer) t1).compareTo((Integer) t2) > 0 ? 1 : -1);
		} else if (ls.get(0) instanceof Long) {
			return ~Collections.binarySearch(ls, x, (t1, t2) -> ((Long) t1).compareTo((Long) t2) > 0 ? 1 : -1);
		} else if (ls.get(0) instanceof Double) {
			return ~Collections.binarySearch(ls, x, (t1, t2) -> ((Double) t1).compareTo((Double) t2) > 0 ? 1 : -1);
		} else {
			System.err.println(
					String.format("%s:数値でないリストを二分探索しています。", Thread.currentThread().getStackTrace()[1].getMethodName()));
			throw new RuntimeException();
		}
	}

	static <T> int rupperBound(List<T> ls, T x) throws RuntimeException {
		if (ls.size() == 0)
			return -1;
		if (ls.get(0) instanceof Integer) {
			return ~Collections.binarySearch(ls, x, (t1, t2) -> ((Integer) t1).compareTo((Integer) t2) < 0 ? 1 : -1);
		} else if (ls.get(0) instanceof Long) {
			return ~Collections.binarySearch(ls, x, (t1, t2) -> ((Long) t1).compareTo((Long) t2) < 0 ? 1 : -1);
		} else if (ls.get(0) instanceof Double) {
			return ~Collections.binarySearch(ls, x, (t1, t2) -> ((Double) t1).compareTo((Double) t2) < 0 ? 1 : -1);
		} else {
			System.err.println(
					String.format("%s:数値でないリストを二分探索しています。", Thread.currentThread().getStackTrace()[1].getMethodName()));
			throw new RuntimeException();
		}
	}

	static <T> int rlowerBound(List<T> ls, T x) {
		if (ls.size() == 0)
			return -1;
		if (ls.get(0) instanceof Integer) {
			return ~Collections.binarySearch(ls, x, (t1, t2) -> ((Integer) t1).compareTo((Integer) t2) <= 0 ? 1 : -1);
		} else if (ls.get(0) instanceof Long) {
			return ~Collections.binarySearch(ls, x, (t1, t2) -> ((Long) t1).compareTo((Long) t2) <= 0 ? 1 : -1);
		} else if (ls.get(0) instanceof Double) {
			return ~Collections.binarySearch(ls, x, (t1, t2) -> ((Double) t1).compareTo((Double) t2) <= 0 ? 1 : -1);
		} else {
			System.err.println(
					String.format("%s:数値でないリストを二分探索しています。", Thread.currentThread().getStackTrace()[1].getMethodName()));
			throw new RuntimeException();
		}
	}

	static int[] concat(int x, int arr[]) {
		int ret[] = new int[arr.length + 1];
		System.arraycopy(arr, 0, ret, 1, ret.length - 1);
		ret[0] = x;
		return ret;
	}

	static int[] concat(int arr[], int x) {
		int ret[] = new int[arr.length + 1];
		System.arraycopy(arr, 0, ret, 0, ret.length - 1);
		ret[ret.length - 1] = x;
		return ret;
	}

	static long[] concat(long x, long arr[]) {
		long ret[] = new long[arr.length + 1];
		System.arraycopy(arr, 0, ret, 1, ret.length - 1);
		ret[0] = x;
		return ret;
	}

	static long[] concat(long arr[], long x) {
		long ret[] = new long[arr.length + 1];
		System.arraycopy(arr, 0, ret, 0, ret.length - 1);
		ret[ret.length - 1] = x;
		return ret;
	}

	static int max(int x, int y) {
		return Math.max(x, y);
	}

	static int min(int x, int y) {
		return Math.min(x, y);
	}

	static int max(int x, int y, int z) {
		x = Math.max(x, y);
		x = Math.max(x, z);
		return x;
	}

	static int min(int x, int y, int z) {
		x = Math.min(x, y);
		x = Math.min(x, z);
		return x;
	}

	static long max(long x, long y) {
		return Math.max(x, y);
	}

	static long min(long x, long y) {
		return Math.min(x, y);
	}

	static long max(long x, long y, long z) {
		x = Math.max(x, y);
		x = Math.max(x, z);
		return x;
	}

	static long min(long x, long y, long z) {
		x = Math.min(x, y);
		x = Math.min(x, z);
		return x;
	}

	static double max(double x, double y) {
		return Math.max(x, y);
	}

	static double min(double x, double y) {
		return Math.min(x, y);
	}

	static double max(double x, double y, double z) {
		x = Math.max(x, y);
		x = Math.max(x, z);
		return x;
	}

	static double min(double x, double y, double z) {
		x = Math.min(x, y);
		x = Math.min(x, z);
		return x;
	}

	static void sort(int[] ar) {
		Arrays.sort(ar);
	}

	static void sort(long[] ar) {
		Arrays.sort(ar);
	}

	static void sort(double[] ar) {
		Arrays.sort(ar);
	}

	static void sort(char[] ar) {
		Arrays.sort(ar);
	}

	static void rsort(int[] ar) {
		Arrays.sort(ar);
		int len = ar.length;
		for (int i = 0; i < len / 2; i++) {
			int tmp = ar[i];
			ar[i] = ar[len - 1 - i];
			ar[len - 1 - i] = tmp;
		}
	}

	static void rsort(long[] ar) {
		Arrays.sort(ar);
		int len = ar.length;
		for (int i = 0; i < len / 2; i++) {
			long tmp = ar[i];
			ar[i] = ar[len - 1 - i];
			ar[len - 1 - i] = tmp;
		}
	}

	static void rsort(double[] ar) {
		Arrays.sort(ar);
		int len = ar.length;
		for (int i = 0; i < len / 2; i++) {
			double tmp = ar[i];
			ar[i] = ar[len - 1 - i];
			ar[len - 1 - i] = tmp;
		}
	}

	static void rsort(char[] ar) {
		Arrays.sort(ar);
		int len = ar.length;
		for (int i = 0; i < len / 2; i++) {
			char tmp = ar[i];
			ar[i] = ar[len - 1 - i];
			ar[len - 1 - i] = tmp;
		}
	}

	static void fill(int arr[], int x) {
		Arrays.fill(arr, x);
	}

	static void fill(long arr[], long x) {
		Arrays.fill(arr, x);
	}

	static void fill(boolean arr[], boolean x) {
		Arrays.fill(arr, x);
	}

	static void fill(double arr[], double x) {
		Arrays.fill(arr, x);
	}

	static void fill(int arr[][], int x) {
		for (int i = 0; i < arr.length; i++)
			Arrays.fill(arr[i], x);
	}

	static void fill(long arr[][], long x) {
		for (int i = 0; i < arr.length; i++)
			Arrays.fill(arr[i], x);
	}

	static void fill(double arr[][], double x) {
		for (int i = 0; i < arr.length; i++)
			Arrays.fill(arr[i], x);
	}

	static void fill(boolean arr[][], boolean x) {
		for (int i = 0; i < arr.length; i++)
			Arrays.fill(arr[i], x);
	}

	//MOD culc
	static long plus(long x, long y) {
		long res = (x + y) % mod;
		return res < 0 ? res + mod : res;
	}

	static long sub(long x, long y) {
		long res = (x - y) % mod;
		return res < 0 ? res + mod : res;
	}

	static long mul(long x, long y) {
		long res = (x * y) % mod;
		return res < 0 ? res + mod : res;
	}

	static long div(long x, long y) {
		long res = x * pow(y, mod - 2) % mod;
		return res < 0 ? res + mod : res;
	}

	static long pow(long x, long y) {
		if (y < 0)
			return 0;
		if (y == 0)
			return 1;
		if (y % 2 == 1)
			return (x * pow(x, y - 1)) % mod;
		long root = pow(x, y / 2);
		return root * root % mod;
	}

	public static void main(String[] args) throws Exception {
		is = INPUT.isEmpty() ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);
		solve();
		out.flush();
	}

	//input
	private static byte[] inbuf = new byte[1024];
	static int lenbuf = 0, ptrbuf = 0;

	private static int readByte() {
		if (lenbuf == -1)
			throw new InputMismatchException();
		if (ptrbuf >= lenbuf) {
			ptrbuf = 0;
			try {
				lenbuf = is.read(inbuf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (lenbuf <= 0)
				return -1;
		}
		return inbuf[ptrbuf++];
	}

	private static boolean isSpaceChar(int c) {
		return !(c >= 33 && c <= 126);
	}

	private static int skip() {
		int b;
		while ((b = readByte()) != -1 && isSpaceChar(b))
			;
		return b;
	}

	@SuppressWarnings("unused")
	private static double nd() {
		return Double.parseDouble(ns());
	}

	@SuppressWarnings("unused")
	private static char nc() {
		return (char) skip();
	}

	private static String ns() {
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while (!(isSpaceChar(b))) {
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	private static char[] ns(int n) {
		char[] buf = new char[n];
		int b = skip(), p = 0;
		while (p < n && !(isSpaceChar(b))) {
			buf[p++] = (char) b;
			b = readByte();
		}
		return n == p ? buf : Arrays.copyOf(buf, p);
	}

	@SuppressWarnings("unused")
	private static char[][] nm(int n, int m) {
		char[][] map = new char[n][];
		for (int i = 0; i < n; i++)
			map[i] = ns(m);
		return map;
	}

	@SuppressWarnings("unused")
	private static int[] na(int n) {
		int[] a = new int[n];
		for (int i = 0; i < n; i++)
			a[i] = ni();
		return a;
	}

	@SuppressWarnings("unused")
	private static long[] nla(int n) {
		long[] a = new long[n];
		for (int i = 0; i < n; i++)
			a[i] = nl();
		return a;
	}

	private static int ni() {
		int num = 0, b;
		boolean minus = false;
		while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'))
			;
		if (b == '-') {
			minus = true;
			b = readByte();
		}

		while (true) {
			if (b >= '0' && b <= '9') {
				num = num * 10 + (b - '0');
			} else {
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	@SuppressWarnings("unused")
	private static long nl() {
		long num = 0;
		int b;
		boolean minus = false;
		while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'))
			;
		if (b == '-') {
			minus = true;
			b = readByte();
		}

		while (true) {
			if (b >= '0' && b <= '9') {
				num = num * 10 + (b - '0');
			} else {
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

}


import java.util.Arrays;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        String[] s = new String[n];
        for (int i = 0; i < n; i++) {
            char[]ss = sc.next().toCharArray();
            Arrays.sort(ss);
            s[i] = new String(ss);
        }
        long ans = 0;
        for (int i = 0; i < n -1; i++) {
            for (int j = i + 1; j < n; j++) {
                if(s[i].contains(s[j])) {
                    ans++;
                }
            }
        }
        System.out.println(ans);
    }
}


import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;

public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();

		Map<String, Integer> set = new HashMap<>();
		for (int i = 0; i < n; i++) {
			String s = sc.next();
			char[] ch = s.toCharArray();
			Arrays.sort(ch);
			String e = new String(ch);

			set.compute(e, (k, v) -> {
				return v == null ? 0 : v + 1;
			});

		}

		long cnt = 0;
		for( Integer it : set.values() ) {
			cnt += it*(it+1)/2;
		}

		System.out.println(cnt);

	}
}


import java.util.ArrayList;
import java.util.Scanner;
import java.util.TreeMap;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        String[] s = new String[n];
        for (int i = 0; i < s.length; i++) {
            s[i] = sc.next();
        }
        ArrayList<TreeMap<Character, Integer>> list = new ArrayList<>();
        for (int i = 0; i < s.length; i++) {
            String tmp = s[i];
            TreeMap<Character, Integer> map = new TreeMap<>();
            for (int j = 0; j < tmp.length(); j++) {
                char key = tmp.charAt(j);
                if(map.containsKey(key)) {
                    map.put(key, map.get(key) + 1);
                }else {
                    map.put(key, 1);
                }
            }
            list.add(map);
        }
        long ans = 0;
        for (int i = 0; i < list.size() - 1; i++) {
            TreeMap<Character, Integer> map = list.get(i);
            for (int j = i + 1; j < list.size(); j++) {
                TreeMap<Character, Integer> map2 = list.get(j);
                if(map.equals(map2)) ans++;
            }
        }
        System.out.println(ans);
    }
}


//#include<bits/stdc++.h>
#include<cstdio>
#include<algorithm>

using namespace std;
typedef long long ll;
#define rep(i, n) for(int i = 0; i < (n); i++)
#define rep1(i, n) for(int i = 1; i <= (n); i++)
#define co(x) cout << (x) << "\n"
#define cosp(x) cout << (x) << " "
#define ce(x) cerr << (x) << "\n"
#define cesp(x) cerr << (x) << " "
#define pb push_back
#define mp make_pair
#define Would
#define you
#define please

//これはひどい提出だ

void pakuri_sort(int N, ll A[]) {
	const int b = 8;
	ll tmp[100001];
	rep(k, 8) {
		int kazu[1 << b] = {}, kazu2[1 << b] = {};
		rep(i, N) kazu[A[i] >> k * b & ((1 << b) - 1)]++;
		rep(i, (1 << b) - 1) kazu[i + 1] += kazu[i];
		for (int i = N - 1; i >= 0; i--) tmp[--kazu[A[i] >> k * b & ((1 << b) - 1)]] = A[i];
		k++;
		rep(i, N) kazu2[tmp[i] >> k * b & ((1 << b) - 1)]++;
		rep(i, (1 << b) - 1) kazu2[i + 1] += kazu2[i];
		for (int i = N - 1; i >= 0; i--) A[--kazu2[tmp[i] >> k * b & ((1 << b) - 1)]] = tmp[i];
	}
}

int main() {
	//cin.tie(0);
	//ios::sync_with_stdio(false);

	const int cm = 1 << 21;
	char cn[cm], * ci = cn;
	fread(cn, 1, cm, stdin);

	int N = 0;
	while (*ci >= '0') N = N * 10 + *ci++ - '0';
	ci++;

	ll are[26];
	are[0] = 1;
	rep(i, 25) are[i + 1] = are[i] * 11;

	ll s[100000];
	rep(i, N) {
		ll k = 0;
		rep(j, 10) k += are[*ci++ - 'a'];
		ci++;
		s[i] = k;
	}

	pakuri_sort(N, s);

	ll kotae = 0;
	ll mae = -1;
	ll kazu = 0;
	rep(i, N) {
		if (mae != s[i]) {
			kotae += kazu * (kazu - 1) / 2;
			mae = s[i];
			kazu = 1;
		}
		else kazu++;
	}

	kotae += kazu * (kazu - 1) / 2;

	printf("%lld", kotae);

	Would you please return 0;
}


#include <algorithm>
#include <iostream>
#include <random>
#include <string>
#include <vector>

// ハッシュ計算で使う素数
constexpr int prime[] = {2,  3,  5,  7,  11, 13,  17,  19, 23, 29,
                         31, 37, 41, 43, 47, 53,  59,  61, 67, 71,
                         73, 79, 83, 89, 97, 101, 103, 107};

constexpr size_t alphabet = 26;
constexpr size_t str_len = 10;

inline int64_t hash(char *str, int start, int end) {
  int64_t result = 1;

  // アルファベット1文字ごとに素数を割り当てて掛け算結果をハッシュ値にする
  // オーバーフローしない限りは完全ハッシュ
  for (size_t i = start; i < end; ++i) {
    result *= prime[str[i] - 'a'];
  }

  return result;
}

int main() {
  int n;
  scanf("%d", &n);
  std::vector<int64_t> sn(n);

  // 最大入力数*1行の文字数(改行込み)
  char input[100000 * 11 + 5];

  // 文字列の一括入力
  fread(input, sizeof(char), sizeof(char) * 11 * n, stdin);

  for (int i = 0; i < n; ++i) {
    // 一文字目に改行(Nの後の改行のこと)が存在するので+1する
    sn[i] = hash(input, i * 11 + 1, i * 11 + 10 + 1);
  }

  // 文字列ソートではなく、数値ソートになる
  // unorderd_map使えばソートなくなるけど遅くなる
  std::sort(sn.begin(), sn.end());

  // 最後に合算する
  int64_t count = 0;
  int64_t local_count = 0;
  for (int i = 1; i < n; ++i) {
    if (sn[i - 1] == sn[i]) {
      count += (++local_count);
    } else {
      local_count = 0;
    }
  }

  // ldで出力しないとWAする
  printf("%ld\n", count);

  return 0;
}


#include <algorithm>
#include <iostream>
#include <random>
#include <string>
#include <vector>

constexpr int prime[] = {2,  3,  5,  7,  11, 13,  17,  19, 23, 29,
                         31, 37, 41, 43, 47, 53,  59,  61, 67, 71,
                         73, 79, 83, 89, 97, 101, 103, 107};

constexpr size_t alphabet = 26;
constexpr size_t str_len = 10;

inline int64_t hash(std::string &str) {
  int64_t result = 1;

  for (size_t i = 0; i < str_len; ++i) {
    result *= prime[str[i] - 'a'];
  }

  return result;
}

inline int64_t hash(char *str, int start, int end) {
  int64_t result = 1;

  for (size_t i = start; i < end; ++i) {
    result *= prime[str[i] - 'a'];
  }

  return result;
}

int main() {
  int n;
  scanf("%d", &n);

  char input[100000 * 11 + 5];

  fread(input, sizeof(char), sizeof(char) * 11 * n, stdin);

  std::vector<int64_t> sn(n);

  for (int i = 0; i < n; ++i) {
    sn[i] = hash(input, i * 11 + 1, i * 11 + 10 + 1);
  }

  std::sort(sn.begin(), sn.end());

  int64_t count = 0;
  int64_t local_count = 0;
  for (int i = 1; i < n; ++i) {
    if (sn[i - 1] == sn[i]) {
      count += (++local_count);
    } else {
      local_count = 0;
    }
  }

  printf("%ld\n", count);

  return 0;
}


#include <bits/stdc++.h>
using namespace std;
int main(void){
    long long int n,i=0,j,c=0,p,m=0,max=0;
    string s[100000];
    cin >> n;
    for(i=0;i<n;i++)
    {
        cin >> s[i];
        sort(s[i].begin(), s[i].end());
    }
    sort(s,s+n);
    for(i=0;i<n;i++)
    {
        if(s[i]==s[i+1])
        {
            m++;
            c++;
        }
        else
        {
            m=0;
        }
        if(m==2)
        {
            c++;
        }
    }
    cout << c << endl;
    return 0;

}


#include <bits/stdc++.h>
using namespace std;
int main(void){
    long long int n,i=0,j,c=0,p,m=0,max=0;
    string s[100000];
    cin >> n;
    for(i=0;i<n;i++)
    {
        cin >> s[i];
        sort(s[i].begin(), s[i].end());
    }
    for(i=0;i<n-1;i++)
    {
        for(j=i+1;j<n;j++)
        {
            if(s[i]==s[j])
            {
                c++;
            }
        }
    }
    cout << c << endl;
    return 0;

}


#include <bits/stdc++.h>
#define _overload3(_1,_2,_3,name,...) name
#define _rep(i,n) repi(i,0,n)
#define repi(i,a,b) for(int i=int(a);i<int(b);++i)
#define rep(...) _overload3(__VA_ARGS__,repi,_rep,)(__VA_ARGS__)
using namespace std;
using ll = long long;
using P = pair<int,int>;
constexpr int INF = 1001001001;
template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }

int main() {
    int n;
    cin >> n;
    vector<string> s(n);
    rep (i, n) {
        cin >> s[i];
        sort(s[i].begin(), s[i].end());
    }

    int ans = 0;
    rep (i, n-1) rep (j, i+1, n)
        if (s[i] == s[j]) ans++;

    cout << ans << endl;

    return 0;
}


#include <stdio.h>

int sort(long *vlist,int *plist,int *qlist,int n){
  int i,j,k,l,m,s=0,p;
  for(i=0;i<n;i++){
    plist[i]=-1;
    qlist[i]=i+1;
  }
  qlist[n-1]=-1;
  while(qlist[s]!=-1){
    i=s;
    p=-1;
    while(i!=-1){
      j=i;
      k=qlist[j];
      if(k==-1) break;
      i=qlist[k];
      if(vlist[j]<vlist[k]){
        if(p==-1){
          s=k;
        }else{
          qlist[p]=k;
        }
        l=j;
        j=k;
        k=l;
      }
      qlist[j]=i;
      p=j;
      while(k!=-1){
        if((j==-1)|(vlist[j]<vlist[k])){
          l=plist[k];
          plist[k]=plist[m];
          plist[m]=k;
          m=k;
          k=l;
        }else{
          m=j;
          j=plist[m];
        }
      }
    }
  }
  return(s);
}

int main(){
  int n,i,k,p[100005],q[100005],c[26];
  long m,j,l[100005],a;
  char s[11];
  for(i=0;i<26;i++){
    c[i]=0;
  }
  scanf("%d",&n);
  for(i=0;i<n;i++){
    scanf("%s",&s);
    l[i]=0;
    k=0;
    for(j=0;j<10;j++){
      c[s[j]-'a']++;
    }
    for(j=0;j<26;j++){
      for(;c[j]>0;c[j]--){
        l[i]|=j<<k;
        k+=5;
      }
    }
  }
  a=0;
  j=0;
  m=0;
  for(i=sort(&l,&p,&q,n);i!=-1;i=p[i]){
    if(a==l[i]){
      j++;
    }else{
      m+=(j*(j+1))>>1;
      j=0;
    }
    a=l[i];
  }
  m+=(j*(j+1))>>1;
  printf("%ld",m);
  return(0);
}


#include <stdio.h>
#include <stdlib.h>

typedef struct List {
	struct List *next;
	char *str;
	long long count;
} list;

int hash_string(char* s)
{
	long long x = 0;
	int i;
	for (i = 0; s[i] != 0; i++)	x += 1 << ((s[i] - 'a') * 2);
	return x % 10007;
}

int anagram(char* s1, char* s2)
{
	int i, count[2][26] = {}, flag = 1;
	for (i = 0; s1[i] != 0; i++) count[0][s1[i] - 'a']++;
	for (i = 0; s2[i] != 0; i++) count[1][s2[i] - 'a']++;
	for (i = 0; i < 26; i++) if (count[0][i] != count[1][i]) break;
	if (i == 26) return 1;
	else return 0;
}

int main()
{
	int i, N;
	char s[100001][11] = {};
	scanf("%d", &N);
	for (i = 1; i <= N; i++) scanf("%s", s[i]);

	int k;
	long long sum = 0;
	list *p, *hash[10007] = {}, data[100001];
	for (i = 1; i <= N; i++) {
		k = hash_string(s[i]);
		for (p = hash[k]; p != NULL; p = p->next) {
			if (anagram(s[i], p->str) == 1) break;
		}
		if (p == NULL) {
			data[i].str = s[i];
			data[i].count = 1;
			data[i].next = hash[k];
			hash[k] = &(data[i]);
		} else (p->count)++;
	}
	for (k = 0; k < 10007; k++) {
		for (p = hash[k]; p != NULL; p = p->next) sum += p->count * (p->count - 1) / 2;
	}
	printf("%lld\n", sum);
	fflush(stdout);
	return 0;
}


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char **GET_ARRAY_CHAR2(long row, long col);
int compare_string(const void *a, const void *b);
void SORT(char s[]);
int main(void) {

   int N;

   scanf("%d",&N);

   char **S = GET_ARRAY_CHAR2(N, 11);

   int i,j;

   for (i = 0; i < N; i++) {
      scanf("%s",S[i]);
      SORT(S[i]);
   }

   qsort(S, N, sizeof *S, compare_string);

   /*
   for (i = 0;i < N;i++) {
      printf("%s\n",S[i]);
   }
    */

   long Ans[N];

   for (i = 0; i < N; i++) {
      Ans[i] = 1;
   }

   int count = 0;
   for (i = 0; i < N - 1; i++) {
      if (strcmp(S[i], S[i+1]) == 0) {
         Ans[count]++;
      }
      else {
         count++;
      }
   }

   long ans = 0;
   for (i = 0; i < N; i++) {
      ans = ans + Ans[i]*(Ans[i] - 1)/2;
   }

   printf("%ld\n", ans);

   return 0;
}

void SORT(char str[]) {

   int i,j;
   char a;

   for (i = 0; str[i] != 0; i++) {
      for (j = i+1; str[j] != 0; j++) {
         if(str[i] > str[j]){
            a = str[i];
            str[i] = str[j];
            str[j] = a;
         }
      }
   }
}

int compare_string(const void *a, const void *b) {
   return strcmp(*(const char **)a, *(const char **)b);
}

char **GET_ARRAY_CHAR2(long row, long col) {

   long i,j;

   char **Matrix;
   Matrix = malloc(sizeof(char*)*row);
   if (Matrix == NULL) {
      printf("Error in GET_ARRAY_CHAR2\n");
      printf("Need More Memory(row=%ld)\n",row);
      exit(1);
   }
   for (i = 0; i < row; i++) {
      Matrix[i] = malloc(sizeof(char)*col);
      if(Matrix[i] == NULL){
         printf("Error in GET_ARRAY_CHAR2\n");
         printf("Need More Memory(col=%ld)\n", col);
         exit(1);
      }
   }

   /*
   for (i = 0; i < row; i++) {
      for (j = 0;j < col; j++) {
         Matrix[i][j] = 0;
      }
   }
   */

   return Matrix;

}


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int cmp(const void * a, const void * b)
{
  return strcmp((char *)a,(char *)b);
}

int main(){
  long long N;
  long long ans =0,j,k,l;

  scanf("%lld", &N);
  char s[N+1][11];

  for(int i=0; i<N; i++)
  {
    scanf("%s",s[i]);
    qsort(s[i],10, sizeof(char), cmp);
  }

  qsort(s,N,sizeof(s[0]),cmp);

  while(j < N){
    if(strcmp(s[j],s[k+1]) == 0){
      ans++;
      ans += l;
      k++;
      l++;
    }else{
      j= k+1;
      k= j;
      l= 0;
    }
  }

  printf("%lld", ans);
  return 0;
}


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int asc(const void *a,const void *b){return (*(char*)a-*(char*)b);}

int main()
{
  int n;
  scanf("%d", &n);
  char s[n][11];
  int i;
  char str[11];
  for (i = 0; i < n; i++)
  {
    scanf("%s", str);
    qsort(str, 10, sizeof(char), asc);
    strcpy(s[i], str);
  }
  qsort(s, n, sizeof(char)*11, asc);
  long ans = 0, cnt = 0;
  for (i = 0; i < n - 1; i++)
  {
    if (strcmp(s[i], s[i+1]) == 0)
    {
      cnt++;
      ans += cnt;
    }
    else
      cnt = 0;
  }
  printf("%ld", ans);
}


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <ctype.h>

#define lli long long int
int c_f(const void *a, const void *b)
{
	return(*(char*)a - *(char*)b);
}

int s_f(const void *a, const void *b)
{
	return(strcmp(*(char **)a, *(char **)b));
}
int main(void)
{
	int n;
	scanf("%d",&n);
	char **s;
	s = (char**)malloc(sizeof(char *)*(n));
	int i = 0;
	while (i < n)
	{
		s[i] = (char *)malloc(sizeof(char)*(12));
		scanf("%s",s[i]);
		qsort(s[i],10,sizeof(char),c_f);
		i++;
	}
	i = 0;
	qsort(s,n,sizeof(char *),s_f);
	//printf("degbug001000\n");
	i = 0;
	int j = 0;
	lli cnt = 0;
	while (i < n-1)
	{
		j = i+1;
		while (j < n && strcmp(s[i],s[j]) == 0 && j < n)
		{
			//printf("debug:i:%d, j:%d\n",i,j);
			//printf("debug:s_i:%s\n",s[i]);
			//printf("debug:s_j:%s\n",s[j]);
			cnt++;
			j++;
		}
		i++;
	}
	printf("%lld\n",cnt);

	return(0);
}


function main(input) {
  const tmp = input.trim().split('\n')
  const n = parseInt(tmp[0])

  const m = new Map()

  for (let i = 1; i <= n; i++) {
    const s = tmp[i]
    const ss = s.split('').sort().join('')

    if (m.has(ss)) {
      m.set(ss, m.get(ss) + 1)
    } else {
      m.set(ss, 1)
    }
  }

  let answer = 0
  m.forEach((v, _) => {
    answer += (v - 1) * v / 2
  })

  console.log(answer)
}
main(require('fs').readFileSync('/dev/stdin', 'utf8'))


function Main(input){
    const sn = input.split('\n');
    const N = sn.shift();
    let answer = 0;
    let box = new Map();
    for(let i=0; i<sn.length; i++){
        const sortStr = sn[i].split('').sort().join('').trim();
        if(box.has(sortStr)){
            answer += box.get(sortStr);
            box.set(sortStr, box.get(sortStr)+1)
        } else{
            box.set(sortStr, 1);
        }
    }
    console.log(answer);
}
Main(require("fs").readFileSync("/dev/stdin", "utf8").trim());


function Main(input) {
  input=input.split("\n");
  if(input[input.length-1]===''){
    input.pop();
  }
  const N=input[0].split(' ')[0]-0;
  var strings=input.slice();
  strings.shift();
  strings=strings.map(e=>{
    return e.split('').sort().join('');
  });
  strings.sort();
  var temp=1;
  var ans=0;
  var previous=strings[0];
  for(var i=1;i<strings.length;i++){
    if(previous===strings[i]){
      temp++;
    }else{
      ans+=temp*(temp-1)/2;
      temp=1;
    }
    previous=strings[i];
  }
  ans+=temp*(temp-1)/2;
  console.log(ans);
}

//*この行以降は編集しないでください（標準入出力から一度に読み込み、Mainを呼び出します）
Main(require("fs").readFileSync("/dev/stdin", "utf8"));


function Main(input){
    const sn = input.split('\n');
    const N = sn.shift();
    let answer = 0;
    let box = new Map();
    for(let i=0; i<sn.length; i++){
        const sortStr = sn[i].split('').sort().join('');
        if(box.has(sortStr)){
            answer++;
        }
        box.set(sortStr);
    }
    // answer += box.size-1
    console.log(answer);
}
Main(require("fs").readFileSync("/dev/stdin", "utf8").trim());


function Main(input){
    const sn = input.split('\n');
    const N = sn.shift();
    let answer = 0;
    let box = new Map();
    for(let i=0; i<sn.length; i++){
        const sortStr = sn[i].split('').sort().join('');
        if(box.has(sortStr)){
            answer++;
        }
        box.set(sortStr);
    }
    // answer += box.size-1
    console.log(answer);
}


function Main(input){
    const sn = input.split('\n');
    const N = sn.shift();
    let answer = 0;
    let box = new Map();
    for(let i=0; i<sn.length; i++){
        const sortStr = sn[i].split('').sort().join('');
        if(box.has(sortStr)){
            answer++;
        }
        box.set(sortStr);
    }
    answer += box.size-1
    console.log(answer);
}
Main(require("fs").readFileSync("/dev/stdin", "utf8").trim());


package main

import (
	"bufio"
	"fmt"
	"math"
	"os"
	"strconv"
)

const (
	initialBufSize = 1024
	maxBufSize     = 1e6
)

var (
	scanner = bufio.NewScanner(os.Stdin)
)

func main() {
	scanner.Split(bufio.ScanWords)
	scanner.Buffer(make([]byte, initialBufSize), maxBufSize)
	n := scanInt()
	anagrams := make(map[string]int, n)
	for i := 0; i < n; i++ {
		s := sort(scanText())
		anagrams[s]++
	}

	ans := 0
	for _, v := range anagrams {
		ans += (v * (v - 1)) / 2
	}

	fmt.Println(ans)
}

func sort(s string) string {
	len := len(s)
	b := []byte(s)
	for i := 0; i < len; i++ {
		min := i
		for j := (i + 1); j < len; j++ {
			if b[j] < b[min] {
				min = j
			}
		}
		b[i], b[min] = b[min], b[i]
	}
	return string(b)
}

func scanInt() int {
	i, _ := strconv.Atoi(scanText())
	return i
}

func scanInts(size int) []int {
	ints := make([]int, size)
	for i := 0; i < size; i++ {
		ints[i] = scanInt()
	}
	return ints
}

func scanFloat64() float64 {
	f, _ := strconv.ParseFloat(scanText(), 64)
	return f
}

func scanFloat64s(size int) []float64 {
	f := make([]float64, size)
	for i := 0; i < size; i++ {
		f[i] = scanFloat64()
	}
	return f
}

func scanText() string {
	scanner.Scan()
	return scanner.Text()
}

func scanTexts(size int) []string {
	s := make([]string, size)
	for i := 0; i < size; i++ {
		s[i] = scanText()
	}
	return s
}

func abs(n int) int {
	return int(math.Abs(float64(n)))
}

func pow(x, y int) int {
	return int(math.Pow(float64(x), float64(y)))
}

func min(n []int) (min, idx int) {
	min = math.MaxInt64
	for i := 0; i < len(n); i++ {
		if n[i] < min {
			min = n[i]
			idx = i
		}
	}
	return
}

func max(n []int) (max, idx int) {
	max = math.MinInt64
	for i := 0; i < len(n); i++ {
		if n[i] > max {
			max = n[i]
			idx = i
		}
	}
	return
}


package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

var sc = bufio.NewScanner(os.Stdin)

func Scan() string {
	sc.Scan()
	return sc.Text()
}
func iScan() int {
	n, _ := strconv.Atoi(Scan())
	return n
}
func fScan() float64 {
	n, _ := strconv.ParseFloat(Scan(), 64)
	return n
}
func stringToInt(s string) int {
	n, _ := strconv.Atoi(s)
	return n
}
func SScan(n int) []string {
	a := make([]string, n)
	for i := 0; i < n; i++ {
		a[i] = Scan()
	}
	return a
}
func iSScan(n int) []int {
	a := make([]int, n)
	for i := 0; i < n; i++ {
		a[i] = iScan()
	}
	return a
}
func abs(x int) int {
	if x < 0 {
		x = -x
	}
	return x
}
func larger(a, b int) int {
	if a < b {
		return b
	} else {
		return a
	}
}
func smaller(a, b int) int {
	if a > b {
		return b
	} else {
		return a
	}
}
func max(a []int) int {
	x := a[0]
	for i := 0; i < len(a); i++ {
		if x < a[i] {
			x = a[i]
		}
	}
	return x
}
func min(a []int) int {
	x := a[0]
	for i := 0; i < len(a); i++ {
		if x > a[i] {
			x = a[i]
		}
	}
	return x
}
func sum(a []int) int {
	x := 0
	for _, v := range a {
		x += v
	}
	return x
}

var mod int = 1000000007

func main() {
	buf := make([]byte, 0)
	sc.Buffer(buf, mod)
	sc.Split(bufio.ScanWords)
	n := iScan()
	s := SScan(n)
	d := make(map[[26]int]int)
	for i := 0; i < n; i++ {
		x := [26]int{}
		for _, v := range s[i] {
			x[int(v)-97]++
		}
		d[x]++
	}
	ans := 0
	for _, v := range d {
		ans += v * (v - 1) / 2
	}
	fmt.Println(ans)
}


//THIS IS A UBER HUGE BLACKISH DICK MOVE!
package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strconv"
)

/********** I/O usage **********/

//str := ReadString()
//i := ReadInt()
//X := ReadIntSlice(n)
//S := ReadRuneSlice()
//a := ReadFloat64()
//A := ReadFloat64Slice(n)

//str := PrintlnInts(X...)

/*******************************************************************/

type freq [26]int

func str2freq(s string) freq {
	var f freq
	for i := 0; i < len(s); i++ {
		f[s[i]-'a']++
	}
	return f
}

func main() {
	n := ReadInt()
	f := make(map[freq]int)
	for i := 0; i < n; i++ {
		s := ReadString()
		f[str2freq(s)]++
	}
	ans := 0
	for _, v := range f {
		ans += v * (v - 1) / 2
	}
	fmt.Println(ans)
}

/*********** Math ***********/
func abs(a int) int {
	if a < 0 {
		return -a
	}
	return a
}

func min(args ...int) int {
	if len(args) == 0 {
		panic("empty!")
	}
	min := args[0]
	for i := 1; i < len(args); i++ {
		if args[i] < min {
			min = args[i]
		}
	}
	return min
}

func max(args ...int) int {
	if len(args) == 0 {
		panic("empty!")
	}
	max := args[0]
	for i := 1; i < len(args); i++ {
		if args[i] > max {
			max = args[i]
		}
	}
	return max
}

func _gcd(a, b int) int {
	if b == 0 {
		return a
	}
	return _gcd(b, a%b)
}

func gcd(args ...int) int {
	if len(args) == 0 {
		panic("empty!")
	}
	gcd := args[0]
	for i := 1; i < len(args); i++ {
		gcd = _gcd(gcd, args[i])
	}
	return gcd
}

/*********** I/O ***********/

var (
	// ReadString returns a WORD string.
	ReadString func() string
	stdout     *bufio.Writer
)

func init() {
	ReadString = newReadString(os.Stdin)
	stdout = bufio.NewWriter(os.Stdout)
}

func newReadString(ior io.Reader) func() string {
	r := bufio.NewScanner(ior)
	r.Buffer(make([]byte, 1024), int(1e+11))
	// Split sets the split function for the Scanner. The default split function is ScanLines.
	// Split panics if it is called after scanning has started.
	r.Split(bufio.ScanWords)

	return func() string {
		if !r.Scan() {
			panic("Scan failed")
		}
		return r.Text()
	}
}

// ReadInt returns an integer.
func ReadInt() int {
	return int(readInt64())
}
func ReadInt2() (int, int) {
	return int(readInt64()), int(readInt64())
}
func ReadInt3() (int, int, int) {
	return int(readInt64()), int(readInt64()), int(readInt64())
}
func ReadInt4() (int, int, int, int) {
	return int(readInt64()), int(readInt64()), int(readInt64()), int(readInt64())
}

func readInt64() int64 {
	i, err := strconv.ParseInt(ReadString(), 0, 64)
	if err != nil {
		panic(err.Error())
	}
	return i
}

// ReadIntSlice returns an integer slice that has n integers.
func ReadIntSlice(n int) []int {
	b := make([]int, n)
	for i := 0; i < n; i++ {
		b[i] = ReadInt()
	}
	return b
}

// ReadFloat64 returns an float64.
func ReadFloat64() float64 {
	return float64(readFloat64())
}

func readFloat64() float64 {
	f, err := strconv.ParseFloat(ReadString(), 64)
	if err != nil {
		panic(err.Error())
	}
	return f
}

// ReadFloatSlice returns an float64 slice that has n float64.
func ReadFloat64Slice(n int) []float64 {
	b := make([]float64, n)
	for i := 0; i < n; i++ {
		b[i] = ReadFloat64()
	}
	return b
}

// ReadRuneSlice returns a rune slice.
func ReadRuneSlice() []rune {
	return []rune(ReadString())
}

// PrintIntsLine returns integers string delimited by a space.
func PrintlnInts(A ...int) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.Itoa(A[i])
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}


package main

import (
	"fmt"
	"sort"
	"strings"
)

func main() {
	var n int
	fmt.Scan(&n)

	dic := make(map[string]int , n)
	for i := 0; i < n; i++ {
		var s string
		fmt.Scan(&s)

		ss := split(s)
		sort.Strings(ss)
		//si = append(si, strings.Join(ss,""))
		str := strings.Join(ss,"")
		curCnt := dic[str]
		if  curCnt == 0 {
			dic[str]++
			continue
		}
		dic[str] +=  curCnt
	}

	cnt := 0
	for _, v := range dic {
		cnt+= v * (v-1) / 2
	}

	fmt.Println(cnt)
}

func split(s string) []string {
	ret := make([]string, len([]rune(s)))
	for i, v := range []rune(s) {
		ret[i] = string(v)
	}
	return ret
}


package main

import (
	"fmt"
	"sort"
	"strings"
)

func main() {
	var n int
	fmt.Scan(&n)

	dic := make(map[string]int , n)
	for i := 0; i < n; i++ {
		var s string
		fmt.Scan(&s)

		ss := split(s)
		sort.Strings(ss)
		//si = append(si, strings.Join(ss,""))
		str := strings.Join(ss,"")
		curCnt := dic[str]
		if  curCnt == 0 {
			dic[str]++
			continue
		}
		dic[str] +=  curCnt
	}

	cnt := 0
	for _, v := range dic {
		if v - 1 > 0 {
			cnt+= v-1
		}
	}

	fmt.Println(cnt)
}

func split(s string) []string {
	ret := make([]string, len([]rune(s)))
	for i, v := range []rune(s) {
		ret[i] = string(v)
	}
	return ret
}


package main

import (
	"fmt"
	"sort"
	"strings"
)

func main() {
	var n int
	fmt.Scan(&n)

	dic := make(map[string]int , n)
	for i := 0; i < n; i++ {
		var s string
		fmt.Scan(&s)

		ss := split(s)
		sort.Strings(ss)
		//si = append(si, strings.Join(ss,""))
		cur := dic[strings.Join(ss,"")]
		if  cur == 0 {
			dic[strings.Join(ss,"")]++
			continue
		}
		dic[strings.Join(ss,"")] +=  dic[strings.Join(ss,"")]
	}

	cnt := 0
	for _, v := range dic {
		if v - 1 > 0 {
			cnt+= v-1
		}
	}

	fmt.Println(cnt)
}

func split(s string) []string {
	ret := make([]string, len([]rune(s)))
	for i, v := range []rune(s) {
		ret[i] = string(v)
	}
	return ret
}


n = gets.to_s.to_i
words = Array.new(n){ gets.to_s.chomp.bytes.sort.pack("U*") }

h = Hash.new()
ans = 0
words.each do |s|

  if h.has_key?(s)
    ans += (h[s] += 1)
  else
    h[s] = 0
  end
end

puts ans


n = gets.to_i
words = Array.new(n){ gets.chomp.bytes.sort.pack("U*") }

h = Hash.new
ans = 0
words.each do |s|

  if h.has_key?(s)
    h[s] += 1
    ans += h[s]
    p
  else
    h[s] = 0
  end
end

puts ans


n = gets.chomp.to_i
ss = n.times.map { gets.chomp }

dict = {}
ss.each do |s|
  key = s.chars.sort.join
  dict[key] = (dict[key] || 0) + 1
end

cnt = 0
dict.each do |k, v|
  next if v <= 1
  cnt += (v * (v - 1)) / 2
end

puts cnt


n=gets.to_i
s=[]
n.times do |i|
  s[i]=gets.chomp.chars
  s[i].sort!
end
s.sort!
a=s.uniq
ans=[]
for i in 0...a.size
  wa=s.count(a[i])
  ans << wa-1 if wa>1
end
for i in 0...ans.size
  ans[i]=(1..ans[i]).inject(0){|sum,k|sum+=k} if ans[i]>1
end
puts ans.sum


n=gets.to_i
s=[]
n.times do |i|
  s[i]=gets.chomp.chars
  s[i].sort!
end
s.sort!
s=s.select{|e|s.count(e)>1}
ans=0
for i in 0...s.size
  j=i+1
  while s[j-1]==s[j]
    j+=1
    ans+=1
  end
end
puts ans


n=gets.to_i
s=[]
n.times do |i|
  s[i]=gets.chomp.chars
  s[i].sort!
end
s.sort!
ans=0
for i in 0...n-1
  j=i+1
  while s[j-1]==s[j]
    j+=1
    ans+=1
  end
end
puts ans


use std::collections::HashMap;

fn read_line() -> String {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).unwrap();
    s.trim_right().to_owned()
}

fn read_stdin() -> String {
    use std::io::Read;
    let mut s = String::new();
    std::io::stdin().read_to_string(&mut s).unwrap();
    s
}

fn count(s: &str) -> [u8; 26] {
    let mut a = [0; 26];
    for c in s.chars() {
        a[(c as u8 - 'a' as u8) as usize] += 1;
    }
    a
}

fn comb2(n: u64) -> u64 {
    n * (n - 1) / 2
}

fn main() {
    read_line();
    let mut h = HashMap::new();
    for s in read_stdin().lines() {
        let c = h.entry(count(s)).or_insert(0);
        *c += 1;
    }

    println!("{}", h.into_iter().map(|(_, n)| comb2(n)).sum::<u64>());
}


use std::io::{self, Write};
use parse::ParseNext;
use std::collections::HashMap;

fn main() {
    let str_count: Vec<u64> = {
        let stdin = io::stdin();
        let mut r = read::Reader::new(io::BufReader::new(stdin));
        let n = r.read_line().unwrap().parse().unwrap();
        let mut str_count = HashMap::with_capacity(n);
        for _ in 0..n {
            let mut s = r.read_line().unwrap().as_bytes().to_vec();
            s.sort();

            let mut count = str_count.entry(s).or_insert(0u64);
            *count += 1;
        }
        str_count.values().map(|x| *x).collect()
    };

    let mut sum = 0;
    for count in str_count {
        sum += count * (count - 1) / 2;
    }

    println!("{}", sum);
}

/// 文字列のパースの補助モジュール.
pub mod parse {
    use std::error;
    use std::fmt;
    use std::str::FromStr;

    #[derive(Eq, PartialEq, Copy, Clone, Hash, Debug)]
    pub enum Error<E> {
        GetNextError,
        ParseErr(E),
    }

    impl<E: fmt::Display> fmt::Display for Error<E> {
        #[inline]
        fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
            match self {
                &Error::GetNextError => f.write_str("Iterator has no next element"),
                &Error::ParseErr(ref e) => write!(f, "{}", e)
            }
        }
    }

    impl<E: error::Error> error::Error for Error<E> {
        #[inline]
        fn description(&self) -> &str {
            match self {
                &Error::GetNextError => "Iterator error",
                &Error::ParseErr(ref e) => e.description()
            }
        }
    }

    pub trait ParseNext: Iterator {
        fn parse_next<F: FromStr>(&mut self) -> Result<F, Error<F::Err>>;
    }

    impl<'a, S: AsRef<str>, I: Iterator<Item=S>> ParseNext for I {
        fn parse_next<F: FromStr>(&mut self) -> Result<F, Error<F::Err>> {
            if let Some(s) = self.next() {
                match s.as_ref().parse() {
                    Ok(x) => Ok(x),
                    Err(e) => Err(Error::ParseErr(e))
                }
            } else {
                Err(Error::GetNextError)
            }
        }
    }
}

/// 標準入力読み取りモジュール.
pub mod read {
    use std::io::{BufRead, Result};

    pub struct Reader<R> {
        buf: String,
        inner: R,
    }

    impl<R> Reader<R> {
        #[inline]
        pub fn new(inner: R) -> Self {
            Reader { buf: String::new(), inner: inner }
        }

        #[inline]
        pub fn into_inner(self) -> R {
            self.inner
        }
    }

    impl<R: BufRead> Reader<R> {
        #[inline]
        pub fn read_line(&mut self) -> Result<&str> {
            self.buf.clear();
            self.inner.read_line(&mut self.buf)?;
            Ok(self.buf.trim_right())
        }
    }
}


fn read_stdin() -> String {
    use std::io::Read;
    let mut input = String::new();
    std::io::stdin().read_to_string(&mut input).unwrap();
    input
}

fn scan<'a, I: Iterator<Item = &'a str>, T: std::str::FromStr>(tokens: &mut I) -> T {
    tokens.next().unwrap().parse().ok().unwrap()
}

fn main() {
    use std::collections::HashMap;
    let input = read_stdin();
    let tokens = &mut input.split_whitespace();
    let n: usize = scan(tokens);
    let mut count = HashMap::new();
    for _ in 0..n {
        let s: String = scan(tokens);
        let mut s = s.into_bytes();
        s.sort();
        *count.entry(s).or_insert(0) += 1;
    }
    let mut ans: usize = 0;
    for &c in count.values() {
        ans += c * (c - 1) / 2;
    }
    println!("{}", ans);
}


use proconio::marker::Chars;
use proconio::{fastout, input};

#[fastout]
fn main() {
    input! {n: usize, s: [Chars; n]};
    let s: Vec<Vec<char>> = s;
    let mut v: Vec<String> = vec![];

    for i in s.iter() {
        let mut c = i.clone();
        c.sort();
        v.push(c.iter().collect::<String>());
    }

    v.sort();

    let mut index = 0;
    let mut count = 0;
    let mut result = 0;

    for i in 1..n {
        if v[i] == v[index] {
            count += 1;
        } else {
            index = i;
            if count > 0 {
                for j in 1..=count {
                    result += j;
                }
            }
            count = 0;
        }

        if i == n - 1 {
            if count > 0 {
                for j in 1..=count {
                    result += j;
                }
            }
        }
    }

    println!("{}", result);
}


use proconio::marker::Chars;
use proconio::{fastout, input};

#[fastout]
fn main() {
    input! {n: usize, s: [Chars; n]};
    let s: Vec<Vec<char>> = s;
    let mut v: Vec<String> = vec![];

    for i in s.iter() {
        let mut c = i.clone();
        c.sort();
        v.push(c.iter().collect());
    }

    v.sort();

    let mut index = 0;
    let mut count = 0;
    let mut result = 0;

    for i in 1..n {
        if v[i] == v[index] {
            count += 1;
        } else {
            index = i;
            if count > 0 {
                if count > 0 {
                    for j in 1..=count {
                        result += j;
                    }
                }
            }
            count = 0;
        }
    }
    if count > 0 {
        for j in 1..=count {
            result += j;
        }
    }

    println!("{}", result);
}


use proconio::marker::Chars;
use proconio::{fastout, input};

#[fastout]
fn main() {
    input! {n: usize, s: [Chars; n]};
    let s: Vec<Vec<char>> = s;
    let mut v: Vec<String> = vec![];

    for i in s.iter() {
        let mut c = i.clone();
        c.sort();
        v.push(c.iter().collect());
    }

    v.sort();

    let mut index = 0;
    let mut count = 0;
    let mut result = 0;

    for i in 1..n {
        if v[i] == v[index] {
            count += 1;
        } else {
            index = i;
            if count > 0 {
                let mut sum = 1;
                if count > 1 {
                    for j in 1..count {
                        sum += 2 + j - 1;
                    }
                }
                result += sum;
            }
            count = 0;
        }
    }
    if count > 0 {
        let mut sum = 1;
        if count > 1 {
            for j in 1..=count {
                sum += j;
            }
        }
        result += sum;
    }

    println!("{}", result);
}


// 🐋💭
import Foundation

func readInts() -> [Int] {
    return readLine()!.split(separator: " ").map { Int($0)! }
}

func readInt() -> Int {
    return Int(readLine()!)!
}

func readDoubles () -> [Double] {
    return readLine()!.split(separator: " ").map { Double($0)! }
}

func readDouble() -> Double{
    return Double(readLine()!)!
}
///最大公約数を返す
func gcd(_ m:Int, _ n:Int) -> Int {
    if n == 0 {return m}
    return gcd(n, m % n)
}

///素数判定(試し割り)
func isPrime(_ x:Int) -> Bool {
    if x <= 1 || x % 2 == 0 { return false }
    if x == 2 { return true }
    for i in stride(from: 3, to: Int(ceil(sqrt(Double(x)))), by: 2){
        if x % i == 0 {
            return false
        }
    }
    return true
}

//https://program-life.com/669
///実行速度の計測
func exectionTime(action: () -> Void) {
    let startDate = Date()
    action()
    let endDate = Date()
    print(endDate.timeIntervalSince(startDate))
}

// https://melheaven.hatenadiary.jp/entry/atcoder144
///約数の配列を返す
func makeDivisors(_ n:Int) -> [Int] {
    var divisors = [Int]()
    for i in 1..<Int(pow(Double(n), 0.5)) + 1 {
        if n % i == 0{
            divisors.append(i + n / i)
        }
    }

    return divisors
}

//https://riptutorial.com/ja/swift/example/14738/インデックスを知らずに配列から要素を削除する
extension Array where Element: Equatable {

    mutating func remove(_ element: Element) {
        _ = index(of: element).flatMap {
            self.remove(at: $0)
        }
    }
}

func binarySearch(rifgt:Int, key:Int, ary:[String]) -> Int{
    var left = 0
    var right = rifgt

    while abs(right - left) > 1 {
        let mid = left + (right - left) / 2

        if Int(ary[mid])! < key {
            left = mid

        } else {
            right = mid
        }
    }
    return left
}

func arrangement (prev:String, ary:[String], returnVal:[String]) -> [String] {
    var returnVal = returnVal
    if ary.count == 0 {
        returnVal.append(prev)
        return returnVal
    }

    for s in ary {
        let wprev = prev + s
        var wary = ary
        wary.remove(s)
        returnVal = arrangement(prev: wprev, ary: wary, returnVal: returnVal)
    }
    return returnVal
}

func main() {
    let n = readInt()
    var aryInput = [String]()
    var ans = 0

    for _ in 1...n {
        let str = readLine()!
        var aryStr = [String]()
        for s in str {
            aryStr.append(String(s))
        }
        aryStr.sort()
        aryInput.append(aryStr.reduce("") { $0 + $1 })
    }

    aryInput.sort()
    var left = 0
    var right = 1
    while right < n {
        while right < n && aryInput[left] == aryInput[right] {
            ans += right - left
            right += 1
        }
        left = right
        right += 1
    }
    print(ans)
}
main()