---------9.28
新的一周 >_<
下午的cf又滚粗了---
不过总比上次爆零好----好忧桑啊--------
cf 581 C
http://codeforces.com/contest/581/problem/C
比赛的时候一直在纠结这两种情况,然后一直贪不出来,然后,居然还去想dp了,,,挫爆
纠结的是这种
37 19 ,k = 3
这种是应该给 37呢,还是给19,然后一直在想要怎么去判断一下怎么加更优-----
其实不用想那么多---sad----
因为每个数的值最多只能够加到100,所以它每次加到整十的收益就是 1,花费就是 10 - a[i] %10
然后像这个例子,就变成 20 39,就好了
然后算每个数最多能够变成多大,统计一下答案就可以了
1 #include2 #include 3 #include 4 #include 5 #include 6 using namespace std; 7 8 //wei ziji jiayou >_<99 9 10 const int maxn = 100005; 11 int a[maxn]; 12 int n,k; 13 14 int cmp(int a,int b){ 15 return a%10 > b%10; 16 } 17 18 void solve(){ 19 sort(a+1,a+n+1,cmp); 20 // for(int i = 1;i <= n;i++) printf("%d ",a[i]); 21 // printf("\n"); 22 23 for(int i = 1;i <= n;i++){ 24 int tmp = 10 - (a[i]%10); 25 if(tmp < 10 && tmp <= k){ 26 a[i] += tmp; 27 k -= tmp; 28 } 29 } 30 31 int res = 0; 32 for(int i = 1;i <= n;i++){ 33 int tmp = 100-a[i]; 34 if(tmp <= k){ 35 a[i] += tmp; 36 k -= tmp; 37 } 38 else{ 39 a[i] += k; 40 k = 0; 41 } 42 res += a[i]/10; 43 } 44 printf("%d\n",res); 45 } 46 47 int main(){ 48 while(scanf("%d %d",&n,&k) != EOF){ 49 for(int i = 1;i <= n;i++) scanf("%d",&a[i]); 50 solve(); 51 } 52 return 0; 53 }
cf 581 d
http://codeforces.com/problemset/problem/581/D
给出三个矩形,问能不能够构成一个正方形
又sad了---
比赛的时候想着怎样去把一个正方形分割成三个矩形,然后去枚举切割位置
情况好多---没有写---
后来这样写的,但是还是感觉有点麻烦
先扫出边界上的矩形,确定下正方形的边长,然后枚举剩下的两个矩形的各种拼接方式,看满不满足
#include#include #include #include #include using namespace std; char g[105]; char res[105][105]; struct node{ int x,y; }a[5]; int x2,y2,x3,y3,x1,y1; int flag; void work(int x2,int y2,int x3,int y3,char c1,char c2){ // printf("x2 = %d y2 = %d x3 = %d y3 = %d c1 = %c c2 = %c\n",x2,y2,x3,y3,c1,c2); if((y3 == y2) && (y3 + x1) == y1 && (x2 + x3) == y1){ flag = 1; for(int i = 1;i <= x2;i++){ for(int j = x1+1;j <= y1;j++) res[i][j] = c1; } for(int i = x2+1;i <= y1;i++){ for(int j = x1+1;j <= y1;j++) res[i][j] = c2; } } if((y2 == y3) && (y2 == y1) && (x1 + x2 + x3) == y1){ flag = 1; for(int i = 1;i <= y1;i++){ for(int j = x1 +1;j <= x1+x2;j++) res[i][j] = c1; } for(int i = 1;i <= y1;i++){ for(int j = x1+x2+1;j <= y1;j++) res[i][j] = c2; } } } void print(){ printf("%d\n",y1); for(int i = 1;i <= y1;i++){ for(int j = 1;j <= y1;j++) printf("%c",res[i][j]); printf("\n"); } printf("\n"); } void solve(){ g[1] = 'A'; g[2] = 'B'; g[3] = 'C'; int maxx = -1; for(int i = 1;i <= 3;i++) { maxx = max(maxx,a[i].x); maxx = max(maxx,a[i].y); } int pos = 0; for(int i = 1;i <= 3;i++){ if(a[i].x == maxx || a[i].y == maxx){ pos = i; break; } } if(a[pos].x > a[pos].y) swap(a[pos].x,a[pos].y); x1 = a[pos].x; y1 = a[pos].y; // printf("x1 = %d y1 = %d\n",x1,y1); for(int i = 1;i <= y1;i++){ for(int j = 1;j <= x1;j++) res[i][j] = g[pos]; } // print(); int ok = 0; char c1,c2; for(int i = 1;i <= 3;i++){ if(i != pos && ok == 0) { x2 = a[i].x; y2 = a[i].y; c1 = g[i]; ok = 1; } if(i != pos && ok){ x3 = a[i].x; y3 = a[i].y; c2 = g[i]; } } flag = 0; work(x2,y2,x3,y3,c1,c2); if(flag) { print(); return; } work(x2,y2,y3,x3,c1,c2); if(flag) { print(); return; } work(y2,x2,x3,y3,c1,c2); if(flag) { print(); return; } work(y2,x2,y3,x3,c1,c2); if(flag) { print(); return; } puts("-1"); } int main(){ while(scanf("%d %d %d %d %d %d",&a[1].x,&a[1].y,&a[2].x,&a[2].y,&a[3].x,&a[3].y) != EOF){ solve(); } return 0; }
没事---下次接着加油----gooooooooooo
---------9.29
cf 501 C
http://codeforces.com/contest/501/problem/C
给出一个森林中每一个节点的度数,以及和它临接的节点的异或和
输出这个森林里面所有的边
先一直没有推出来是,那个邻接的异或和没有搞清楚,是所有的邻接的顶点的异或和
然后就从叶子节点开始找,叶子节点的异或和,就是这条边的另一端,然后就一层一层这样找下去
1 #include2 #include 3 #include 4 #include 5 #include 6 #include 7 using namespace std; 8 9 const int maxn = 1000005; 10 typedef pair<int,int> pii; 11 12 int d[maxn],x[maxn]; 13 int n; 14 15 void solve(){ 16 queue<int> q; 17 vector res; 18 for(int i = 0; i < n;i++) if(d[i] == 1) q.push(i); 19 20 while(!q.empty()){ 21 int u = q.front();q.pop(); 22 if(d[u] == 0) continue; 23 // printf("d[%d] = %d x[%d] = %d\n",u,d[u],u,x[u]); 24 25 d[u]--; 26 int v = x[u]; 27 res.push_back(make_pair(u,v)); 28 x[v] = x[v]^u; 29 d[v]--; 30 if(d[v] == 1) q.push(v); 31 } 32 printf("%d\n",res.size()); 33 for(int i = 0;i < res.size();i++){ 34 printf("%d %d\n",res[i].first,res[i].second); 35 } 36 } 37 38 int main(){ 39 while(scanf("%d",&n) != EOF){ 40 memset(d,0,sizeof(d)); 41 memset(x,0,sizeof(x)); 42 for(int i = 0;i < n;i++){ 43 scanf("%d %d",&d[i],&x[i]); 44 } 45 solve(); 46 } 47 return 0; 48 }
hdu 5489
给出一列数,删除连续的k个数之后,求最长的LIS的长度
比赛的时候,一直想的是拼接的办法,就是枚举切割的点,然后将两段的LIS加起来,维持一个最大值
可是,这样不对,因为不能够保证这两段能不能够拼接起来
后来看题解---
还是分成两段的办法
假设当前的位置是 i,i位置对应的值为 v,离散化后对应的值为y
然后建立一颗线段树
每次查询[0,y-1] 对应的最大dp值(这样就可以保证两段可以拼接起来),加上以i为起点的最长LIS的长度
再维持一个最大值
最后还要和不拼接的两种情况比较一下,就是删去最前面一段,和删去最后面一段
-----觉得线段树写得太少了,,,改了好久的说,离散化写得也好挫,,看别人的写的几十行就写完了-------
没事-----------------加油 ---->_<
1 #include2 #include 3 #include 4 #include 5 #include 6 using namespace std; 7 8 #define getmid(l,r) l + (r-l)/2 9 10 // wei ziji jiayou >_< 11 12 const int maxn = 100005; 13 const int INF = (1<<30)-1; 14 int g[maxn],a[maxn],L[maxn],R[maxn]; 15 int n,k; 16 int b[maxn]; 17 int nmax; 18 19 struct Node{ 20 int x,id; 21 }p[maxn]; 22 23 struct node{ 24 int l,r,maxx; 25 }t[4*maxn]; 26 27 int cmp(Node n1,Node n2){ 28 return n1.x < n2.x; 29 } 30 int cmp1(Node n1,Node n2){ 31 return n1.id < n2.id; 32 } 33 34 void init() { 35 for(int i = 1; i <= n; i++) g[i] = INF; 36 for(int i = 1; i <= n; i++) { 37 int k = lower_bound(g+1, g+1+n, a[i]) - g; 38 L[i] = k; 39 g[k] = a[i]; 40 } 41 for(int i = 1; i <= n; i++) a[i] = -a[i]; 42 for(int i = 1; i <= n; i++) g[i] = INF; 43 for(int i = n; i > 0; i--) { 44 int k = lower_bound(g+1, g+1+n, a[i]) - g; 45 R[i] = k; 46 g[k] = a[i]; 47 } 48 } 49 50 void Push_up(int p){ 51 t[p].maxx = max(t[p<<1].maxx,t[p<<1|1].maxx); 52 } 53 54 void Build_tree(int p,int l,int r){ 55 t[p].l = l; 56 t[p].r = r; 57 if(l == r){ 58 t[p].maxx = 0; 59 return; 60 } 61 int mid = getmid(l,r); 62 Build_tree(p<<1,l,mid); 63 Build_tree(p<<1|1,mid+1,r); 64 Push_up(p); 65 } 66 67 void Update(int p,int s,int w){ 68 if(t[p].l == t[p].r){ 69 t[p].maxx = w; 70 return; 71 } 72 int mid = getmid(t[p].l,t[p].r); 73 if(s <= mid) Update(p<<1,s,w); 74 else Update(p<<1|1,s,w); 75 Push_up(p); 76 } 77 78 void query(int p,int l,int r){ 79 if(t[p].maxx <= nmax) return; 80 if(t[p].l == l && t[p].r == r){ 81 nmax = max(t[p].maxx,nmax); 82 return; 83 } 84 int mid = getmid(t[p].l,t[p].r); 85 if(r <= mid) query(p<<1,l,r); 86 else if(l > mid) query(p<<1|1,l,r); 87 else { 88 query(p<<1,l,mid); 89 query(p<<1|1,mid+1,r); 90 } 91 } 92 93 void solve(){ 94 memset(L,0,sizeof(L)); 95 memset(R,0,sizeof(R)); 96 init(); 97 for(int i = 1;i <= n;i++) p[i].id = i, p[i].x = -a[i]; 98 sort(p+1,p+n+1,cmp); 99 for(int i = 1,j = 0;i <= n;i++){ 100 if(i == 1 || p[i].x != p[i-1].x) j++; 101 b[p[i].id] = j; 102 } 103 104 Build_tree(1,1,n); 105 106 sort(p+1,p+n+1,cmp1); 107 int res = 0; 108 for(int i = k+1;i <= n;i++){ 109 int pos = b[p[i].id]; 110 nmax = 0; 111 if(pos-1 > 0) query(1,1,pos-1); 112 113 int tmp = nmax; 114 115 res = max(res,tmp+R[i]); 116 int pos1 = b[p[i-k].id]; 117 118 // printf("i = %d pos = %d tmp = %d pos1 = %d\n",i,pos,tmp,pos1); 119 Update(1,pos1,L[i-k]); 120 } 121 // printf("res = %d\n",res); 122 res = max(res,max(L[n-k],R[k+1])); 123 printf("%d\n",res); 124 } 125 126 int main(){ 127 int T; 128 scanf("%d",&T); 129 int kase = 0; 130 while(T--){ 131 scanf("%d %d",&n,&k); 132 for(int i = 1;i <= n;i++) scanf("%d",&a[i]); 133 printf("Case #%d: ",++kase); 134 solve(); 135 } 136 return 0; 137 }
hdu 5475
感觉思路好巧妙啊----,把除法的转化成乘法了
如果操作是1的话,就把a[i]更新成为要乘的那个数
如果操作是2的话,就把a[a[i]]更新成1
然后询问就是输出区间1到i的乘积,这会儿再取模
1 #include2 #include 3 #include 4 #include 5 #include 6 using namespace std; 7 8 //wei ziji jiayou >_< 9 10 #define getmid(l,r) l +(r-l)/2 11 12 typedef long long LL; 13 const int maxn = 100005; 14 int a[maxn]; 15 int n,m; 16 LL ans[maxn]; 17 18 struct node{ 19 int l,r; 20 LL c; 21 }t[4*maxn]; 22 23 void Push_up(int p){ 24 t[p].c = t[p<<1].c * t[p<<1|1].c % m; 25 } 26 27 void Build_tree(int p,int l,int r){ 28 t[p].l = l; 29 t[p].r = r; 30 if(l == r){ 31 t[p].c = 1; 32 return; 33 } 34 int mid = getmid(l,r); 35 Build_tree(p<<1,l,mid); 36 Build_tree(p<<1|1,mid+1,r); 37 Push_up(p); 38 } 39 40 void Update(int p,int s,int w){ 41 if(t[p].l == t[p].r ){ 42 t[p].c = w; 43 return; 44 } 45 int mid = getmid(t[p].l,t[p].r); 46 if(s <= mid) Update(p<<1,s,w); 47 else Update(p<<1|1,s,w); 48 Push_up(p); 49 } 50 51 LL Query(int p,int l,int r){ 52 if(t[p].l == l && t[p].r == r){ 53 return t[p].c; 54 } 55 int mid = getmid(t[p].l,t[p].r); 56 if(r <= mid) return Query(p<<1,l,r); 57 else if(l > mid) return Query(p<<1|1,l,r); 58 else return Query(p<<1,l,mid) * Query(p<<1|1,mid+1,r) %m; 59 } 60 61 void solve(){ 62 Build_tree(1,1,n); 63 // for(int i = 1;i <= 2*n;i++) printf("t[%d].c = %I64d l = %d r = %d\n",i,t[i].c,t[i].l,t[i].r); 64 memset(ans,0,sizeof(ans)); 65 for(int i = 1;i <= n;i++){ 66 int op; 67 scanf("%d %d",&op,&a[i]); 68 if(op == 1) Update(1,i,a[i]); 69 else Update(1,a[i],1); 70 LL res = Query(1,1,i) % m; 71 // printf("%I64d\n",res); 72 ans[i] = res; 73 } 74 for(int i = 1;i <= n;i++) printf("%I64d\n",ans[i]); 75 } 76 77 int main(){ 78 int T; 79 scanf("%d",&T); 80 int kase = 0; 81 while(T--){ 82 scanf("%d %d",&n,&m); 83 printf("Case #%d:\n",++kase); 84 solve(); 85 } 86 return 0; 87 }
cf 522 a
http://codeforces.com/problemset/problem/522/A
DAG上的最长路
定义成 string s1
然后写的时候直接用的s1[i],会RE,,,,不懂用stirng,还是改成char 了----
1 #include2 #include 3 #include 4 #include 5 #include
---------9.30
cf 234 C
http://codeforces.com/problemset/problem/234/C
改变最少的数,使得这列数的前面一段为负数,后面一段为正数
递推求出负数和零的个数,然后枚举一下断开的点
1 #include2 #include 3 #include 4 #include 5 using namespace std; 6 7 const int maxn = 100005; 8 int a[maxn],sum[maxn],ling[maxn]; 9 int n; 10 11 void solve(){ 12 memset(sum,0,sizeof(sum)); 13 memset(ling,0,sizeof(ling)); 14 int c = 0; 15 16 if(n == 2){ 17 int res = 0; 18 if(a[1] >= 0) res++; 19 if(a[2] <= 0) res++; 20 printf("%d\n",res); 21 return; 22 } 23 24 for(int i = 1;i <= n;i++){ 25 if(a[i] < 0) sum[i] = sum[i-1]+1; 26 else sum[i] = sum[i-1]; 27 28 if(a[i] == 0) ling[i] = ling[i-1]+1,c++; 29 else ling[i] = ling[i-1]; 30 } 31 32 //for(int i = 1;i <= n;i++) printf("sum[%d] = %d ling[%d] = %d\n",i,sum[i],i,ling[i]); 33 34 int res = (1<<30)-1; 35 for(int i = 2;i <= n-1;i++){ 36 int l =(i-1)-sum[i-1] -ling[i-1];//suan zhengshu 37 int r = sum[n]-sum[i];//suan fushu 38 res = min(res,l+r); 39 // printf("i = %d l = %d r = %d\n",i,l,r); 40 } 41 printf("%d\n",res+c); 42 } 43 44 int main(){ 45 freopen("input.txt","r",stdin); 46 freopen("output.txt","w",stdout); 47 while(scanf("%d",&n) != EOF){ 48 memset(a,0,sizeof(a)); 49 for(int i = 1;i <= n;i++) scanf("%d",&a[i]); 50 solve(); 51 } 52 return 0; 53 }
cf 219 C
http://codeforces.com/problemset/problem/219/C
给出k个不同的字母,再给出一个字符串
替换最少的字母,使得这个字符串里面相邻的两个字母都不相同
先贪错了,,,顺着扫一遍,再逆着扫一遍--这样不对
应该从k的个数来考虑
如果 k == 2,就只能够是 ABABABA,BABABAB这两种情况,判断一下哪种更少就可以了
如果 k >= 3,所以相邻的相同的一定可以找到第三个来和它们不一样,直接扫一遍就可以了
1 #include2 #include 3 #include 4 #include 5 #include 6 using namespace std; 7 8 //wei ziji jiayou >_< 9 10 const int maxn = 500005; 11 char s[maxn],t[maxn],e[maxn]; 12 int n,k; 13 14 void solve(){ 15 if(k == 2){ 16 int c1 = 0,c2 = 0; 17 for(int i = 1;i <= n;i++){ 18 if(i%2 == 1) t[i] = 'A'; 19 else t[i] = 'B'; 20 if(s[i] != t[i]) c1++; 21 } 22 23 for(int i = 1;i <= n;i++){ 24 if(i%2 == 1) e[i] = 'B'; 25 else e[i] = 'A'; 26 if(s[i] != e[i]) c2++; 27 } 28 printf("%d\n",min(c1,c2)); 29 if(c1 <= c2) printf("%s\n",t+1); 30 else printf("%s\n",e+1); 31 return; 32 } 33 34 int c = 0; 35 for(int i = 2;i <= n;i++){ 36 if(s[i] == s[i-1]){ 37 for(int j = 1;j <= k;j++){ 38 int u = s[i]-'A'+1; 39 int v = s[i+1]-'A'+1; 40 if(j != u && j != v){ 41 s[i] = j+'A'-1; 42 c++; 43 break; 44 } 45 } 46 } 47 } 48 printf("%d\n",c); 49 printf("%s\n",s+1); 50 } 51 52 int main(){ 53 while(scanf("%d %d",&n,&k) != EOF){ 54 scanf("%s",s+1); 55 solve(); 56 } 57 return 0; 58 }
cf 407 b
http://codeforces.com/contest/407/problem/B
给出n个房间,给出pi
如果是第奇数次走到这个房间,那么接下来他就去到pi
如果是第偶数次走到这个房间,那么接下来他就去到i+1
问从第1间房间到达第n+1间房间至少需要走多少步
被绕晕了-----
用cnt[i]记录下来,第一次到i ------到兜完一圈再次到达i需要的步数
cnt[i] = sigma cnt[k] + i-pi +1,pi <= k < i
这个画下图,推下样例可以得到
然后dp[i] = dp[i-1] + cnt[i] + 1
然后求的就是dp[n+1],
其实还是不太懂,画画图,凑了凑样例,凑的---
1 #include2 #include 3 #include 4 #include 5 #include 6 using namespace std; 7 8 const int mod = 1e9+7; 9 const int maxn = 100005; 10 int dp[maxn],cnt[maxn]; 11 int n,p[maxn]; 12 13 void solve(){ 14 memset(dp,0,sizeof(dp)); 15 memset(cnt,0,sizeof(cnt)); 16 17 for(int i = 1;i <= n;i++){ 18 for(int j = p[i];j < i;j++) cnt[i] = (cnt[i] + cnt[j]) % mod; 19 20 cnt[i] = (cnt[i] + i-p[i]+1)%mod; 21 // printf("cnt[%d] = %d\n",i,cnt[i]); 22 } 23 24 for(int i = 2;i <= n+1;i++){ 25 dp[i] = (dp[i-1] + cnt[i-1] + 1)%mod; 26 // printf("dp[%d] = %d\n",i,dp[i]); 27 } 28 printf("%d\n",dp[n+1]); 29 } 30 31 int main(){ 32 while(scanf("%d",&n) != EOF){ 33 memset(p,0,sizeof(p)); 34 for(int i = 1;i <= n;i++) scanf("%d",&p[i]); 35 36 solve(); 37 } 38 return 0; 39 }
---------10.1
弱校联萌第一天-
---------10.2
弱校联萌第二天
---------10.3
弱校联萌第一天 J Right turn
http://www.bnuoj.com/v3/contest_show.php?cid=6865#problem/J
一神教的办法>_<
先记录下方向,然后暴力找到最近的障碍物,如果有就转弯,如果没有,就直接出去了
1 #include2 #include 3 #include 4 #include 5 #include 6 using namespace std; 7 8 const int maxn = 1005; 9 int n; 10 const int INF = (1<<30)-1; 11 12 struct node{ 13 int x,y; 14 }a[maxn]; 15 16 void solve(){ 17 int sx,sy,nx,ny; 18 int res = 0; 19 int ok = 0; 20 sx = 0;sy = 0; 21 for(;;){ 22 for(int i = 0;i < 4;i++){ 23 if(i == 0){ 24 nx = INF; 25 ok = 0; 26 for(int j = 1;j <= n;j++){ 27 if(a[j].y == sy){ 28 if(a[j].x > sx){ 29 nx = min(a[j].x,nx); 30 ok = 1; 31 } 32 } 33 } 34 sx = nx-1; 35 } 36 37 if(i == 3){ 38 ny = INF; 39 ok = 0; 40 for(int j = 1;j <= n;j++){ 41 if(a[j].x == sx){ 42 if(a[j].y > sy){ 43 ny = min(ny,a[j].y); 44 ok = 1; 45 } 46 } 47 } 48 sy = ny-1; 49 } 50 if(i == 2){ 51 nx = -INF; 52 ok = 0; 53 for(int j = 1;j <= n;j++){ 54 if(a[j].y == sy){ 55 if(a[j].x < sx){ 56 nx = max(a[j].x,nx); 57 ok = 1; 58 } 59 } 60 } 61 sx = nx+1; 62 } 63 if(i == 1){ 64 ny = -INF; 65 ok = 0; 66 for(int j = 1;j <= n;j++){ 67 if(a[j].x == sx){ 68 if(a[j].y < sy){ 69 ny = max(ny,a[j].y); 70 ok = 1; 71 } 72 } 73 } 74 sy = ny+1; 75 } 76 77 //printf("i = %d sx = %d sy = %d\n",i,sx,sy); 78 79 if(ok == 0){ 80 printf("%d\n",res); 81 return; 82 } 83 else res++; 84 85 if(res > 5000){ 86 puts("-1"); 87 return; 88 } 89 } 90 } 91 } 92 93 int main(){ 94 while(scanf("%d",&n) != EOF){ 95 for(int i = 1;i <= n;i++){ 96 scanf("%d %d",&a[i].x,&a[i].y); 97 } 98 solve(); 99 } 100 return 0; 101 }
弱校联萌第一天 B Carries
http://www.bnuoj.com/v3/contest_show.php?cid=6865#problem/B
把所有的个位,十位,百位,-----,千万位分别放进一个vector,排序后,再挨次找能够让它进位的数有多少个
终于知道wa了一天哪儿错了-----555555555555555
10^9是9个0,不是8个0------------要找到亿位-------
1 #include2 #include 3 #include 4 #include 5 #include 6 using namespace std; 7 8 typedef long long LL; 9 const int maxn = 100005; 10 vector<int> b[15]; 11 int n; 12 int a[maxn]; 13 int c[15][maxn]; 14 15 int ge(int x){ 16 return x%10; 17 } 18 19 int sh(int x){ 20 return (x/10%10)*10 + ge(x); 21 } 22 23 int ba(int x){ 24 return (x/100%10)*100 + sh(x); 25 } 26 27 int qi(int x){ 28 return (x/1000%10)*1000+ba(x); 29 } 30 31 int wa(int x){ 32 return (x/10000%10)*10000 + qi(x); 33 } 34 35 int sw(int x){ 36 return (x/100000%10)*100000 + wa(x); 37 } 38 39 int bw(int x){ 40 return (x/1000000%10)*1000000 + sw(x); 41 } 42 43 int qw(int x){ 44 return (x/10000000%10)*10000000+bw(x); 45 } 46 47 int yi(int x){ 48 return (x/100000000%10)*100000000+qw(x); 49 } 50 51 void work(int x){ 52 b[1].push_back(ge(x)); 53 b[2].push_back(sh(x)); 54 b[3].push_back(ba(x)); 55 b[4].push_back(qi(x)); 56 b[5].push_back(wa(x)); 57 b[6].push_back(sw(x)); 58 b[7].push_back(bw(x)); 59 b[8].push_back(qw(x)); 60 b[9].push_back(yi(x)); 61 } 62 63 void solve(){ 64 memset(c,0,sizeof(c)); 65 for(int i = 1;i <= 10;i++) b[i].clear(); 66 67 for(int i = 1;i <= n;i++) work(a[i]); 68 for(int i = 1;i <= 9;i++) sort(b[i].begin(),b[i].end()); 69 70 for(int i = 1;i <= 9;i++){ 71 for(int j = 0;j < b[i].size();j++) { 72 c[i][j] = b[i][j]; 73 //printf("%d ",b[i][j]); 74 } 75 // printf("\n"); 76 } 77 78 LL res = 0; 79 for(int i = 1;i <= 9;i++){ 80 for(int j = 0;j < b[i].size();j++){ 81 int tmp; 82 int x; 83 if(i == 1)tmp = lower_bound(c[i]+j,c[i]+b[i].size(),10-ge(b[i][j]))-c[i],x = 10-ge(b[i][j]); 84 if(i == 2)tmp = lower_bound(c[i]+j,c[i]+b[i].size(),100-sh(b[i][j]))-c[i],x = 100-sh(b[i][j]); 85 if(i == 3)tmp = lower_bound(c[i]+j,c[i]+b[i].size(),1000-ba(b[i][j]))-c[i],x = 1000-ba(b[i][j]); 86 if(i == 4)tmp = lower_bound(c[i]+j,c[i]+b[i].size(),10000-qi(b[i][j]))-c[i],x = 10000-qi(b[i][j]); 87 if(i == 5)tmp = lower_bound(c[i]+j,c[i]+b[i].size(),100000-wa(b[i][j]))-c[i],x = 100000-wa(b[i][j]); 88 if(i == 6)tmp = lower_bound(c[i]+j,c[i]+b[i].size(),1000000-sw(b[i][j]))-c[i],x = 1000000-sw(b[i][j]); 89 if(i == 7)tmp = lower_bound(c[i]+j,c[i]+b[i].size(),10000000-bw(b[i][j]))-c[i],x = 10000000- bw(b[i][j]); 90 if(i == 8)tmp = lower_bound(c[i]+j,c[i]+b[i].size(),100000000-qw(b[i][j]))-c[i],x = 100000000-qw(b[i][j]); 91 if(i == 9)tmp = lower_bound(c[i]+j,c[i]+b[i].size(),1000000000-yi(b[i][j]))-c[i],x = 1000000000-yi(b[i][j]); 92 int l = 0; 93 if(tmp == j) l = b[i].size()-tmp-1; 94 else { 95 if(tmp == b[i].size()) l = 0; 96 else l = b[i].size()-tmp; 97 } 98 99 //printf("i = %d tmp = %d l = %d x = %d\n",i,tmp,l,x); 100 res += 1LL*l; 101 } 102 //printf("\n\n"); 103 } 104 printf("%lld\n",res); 105 } 106 107 int main(){ 108 while(scanf("%d",&n) != EOF){ 109 memset(a,0,sizeof(a)); 110 111 for(int i = 1;i <= n;i++) scanf("%d",&a[i]); 112 solve(); 113 } 114 return 0; 115 }