IT spotlight-TrueNorth by IBM

TrueNorth:IBM的百万神经元类人脑芯片

邮票大小、重量只有几克,但却集成了54亿个硅晶体管,内置了4096个内核,100万个“神经元”、2.56亿个“突触”,能力相当于一台超级计算机,功耗却只有65毫瓦。

这就是IBM公布的最新仿人脑芯片:TrueNorth。

为什么要做TrueNorth?

因为自2008年以来,美国国防部研究机构DARPA给了IBM 5300万美元。TrueNorth是IBM参与DARPA的研究项目SyNapse的最新成果。SyNapse全称是Systems of Neuromorphic Adaptive Plastic Scalable Electronics(自适应可塑可伸缩电子神经系统,而SyNapse正好是突触的意思),其终极目标是开发出打破冯 诺依曼体系的硬件。

为什么要打破冯 诺依曼体系?

冯 诺依曼体系是传统计算机的基础。这种体系的特点是存放信息和程序指令的内存与处理信息的处理器是分离的。由于处理器是按照线序执行指令的,所以必须不断与内存通过总线反复交换信息—而这个会成为拖慢速度和浪费能量的瓶颈。尽管后来采用了多核芯片和缓存技术,但是这些只能提高速度而不能降低太多能耗,而且没办法实时处理,因为通信是瓶颈—内存和CPU的大量通信要通过总线进行。因此,近几十年来研究人员一直在致力于寻找突破原有体系的技术。

模仿大脑

模仿人类大脑是科学家寻求突破的方向。人类大脑的神经元尽管传导信号的速度很慢,但是却拥有庞大的数量(千亿级),而且每个神经元都通过成千上万个突触与其他神经元相连,形成超级庞大的神经元回路,以分布式和并发式的方式传导信号,相当于超大规模的并行计算,从而弥补了单神经元处理速度的不足。人脑的另一个特点是部分神经元不使用时可以关闭,从而整体能耗很低。

【转】核心网络—BestCoder需要注意的几个问题

核心网络—BestCoder需要注意的几个问题.

1.不能随意hack,hack成功有加分,但是hack失败也会扣分!
2.不要随意提交已经AC的题目,罚时是这样的:最后一次AC的之前所有提交(无论AC与否)均算作罚时!其中AC的标为Accepted(Past),被hack掉的AC也会标为Accepted(Past)。
3.AC不代表真正的AC,比赛最后阶段有hack数据,如果被hack掉就不算AC。hack数据一般都是非常变态的输入,或者是大数据!有时候有些人刻意利用题目bug构造变态的数据导致全场无人AC……
4.hack时只能读别人的代码,无法复制,这是锻炼读代码的能力。
5.如果有一场比赛注册了,但是忘做了,只要没有该场比赛的提交记录就不会使Rating降低。
6.只有本场比赛进入前300才能使Rating升高,否则就降低。
7.ABCD四道题的难度是依次升高的,分数也是依次升高的,根据错的次数和AC时间而使所得分数不同。
8.比赛题目是民间的ACMer出的,如果发现题目中有大量的英语语法错误,请不要见怪。
9.比赛日期并非固定在周五或者周六或者周日,根据杭电oj的具体日程安排而定。比如,如果有网络赛,可能就要提前或者延后了。
10.最后你的很多AC的题目可能都会被hack掉,请不要见怪。
11.

以上错误我几乎都犯过……
O__O”…

【Bestcoder

1001 - Rikka with string

Accepts: 395
Submissions: 2281
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)
Problem Description

As we know, Rikka is poor at math. Yuta is worrying about this situation, so he gives Rikka some math tasks to practice. There is one of them:

One day, Yuta got a string which contains n letters but Rikka lost it in accident. Now they want to recover the string. Yuta remembers that the string only contains lowercase letters and it is not a palindrome string. Unfortunately he cannot remember some letters. Can you help him recover the string?

It is too difficult for Rikka. Can you help her?
Input

This problem has multi test cases (no more than 20). For each test case, The first line contains a number n(1≤n≤1000). The next line contains an n-length string which only contains lowercase letters and ‘?’ – the place which Yuta is not sure.
Output

For each test cases print a n-length string – the string you come up with. In the case where more than one string exists, print the lexicographically first one. In the case where no such string exists, output “QwQ”.
Sample Input

5
a?bb?
3
aaa

Sample Output

aabba
QwQ

WA得智商都被拉低了 QAQ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int dfs(int step,bool &state)//1:to check
{
int res;
if (step<m-1) res=dfs(step+1,state);
int pos=n-vec[step]-1;
cout<<step<<' '<<str[vec[step]]<<' '<<str[pos]<<endl;
for(char ch='a';ch<='z';ch++)
if (state&&str[pos]==ch)
{
if (ch<'z') continue;
else return -1;//error
}
else
{
str[vec[step]]=ch;
if (state&&str[pos]!='?'&&ch!=str[pos]) state=0;
if (ch!=str[pos]) return 1;
}
return -1;
}

AC:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include<cctype>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<queue>
#include<stack>
#include<set>
#include<map>
#define CLEAR(a) memset((a),0,sizeof((a)))

using namespace std;

typedef long long LL;
const double pi = acos(-1.0);
const int maxn=2e3;
const int inf=99999999;
const float eps=1e-3;

vector<int> vec;
int n,m;
char s[maxn],str[maxn];

int dfs(int step,bool &state)//1:to check
{

int pos=n-vec[step]-1;
for(char ch='a';ch<='z';ch++)
{
str[vec[step]]=ch;
if (str[pos]!='?'&&ch!=str[pos]) {state=0;}
if (step<m-1) dfs(step+1,state);
if (state&&str[pos]!='?'&&ch!=str[pos]||!state) return 1;
}

return -1;
}

int main()
{

while(~scanf("%d",&n))
{
vec.clear();
scanf("%s",s);
memcpy(str,s,sizeof(s));
for(int i=0;i<n;i++)
if (s[i]=='?')
vec.push_back(i);
m=vec.size();
bool tmp=1;

if (m>1||m==1&&!(n%2&&vec[0]==n/2))
{
if (dfs(0,tmp)>=0) puts(str);
else puts("QwQ");
}
else
{
bool ans=1;
for(int i=1;i<=strlen(s)/2;i++)
if (s[i-1]!=s[strlen(s)-i])
{
ans=0;break;
}
if (m==1&&n%2&&vec[0]==n/2) str[vec[0]]='a';
puts(ans?"QwQ":str);
}

}
return 0;
}

[心痛]线段树或树状数组求逆序数

原文地址

线段树或树状数组求逆序数

求逆序数的方法有分治,归并,本文只介绍线段树或树状数组求逆序数的办法,众所周知,线段树和树状树可以用来解决区间操作问题,就是因为这两个算法区间操作的时间复杂度很低O(logN),才让这种方法具有可行性。

首先先来看一个序列   6 1 2 7 3 4 8 5,此序列的逆序数为5+3+1=9。冒泡法可以直接枚举出逆序数,但是时间复杂度太高O(n^2)。冒泡排序的原理是枚举每一个数组,然后找出这个数后面有多少个数是小于这个数的,小于它逆序数+1。仔细想一下,如果我们不用枚举这个数后面的所有数,而是直接得到小于这个数的个数,那么效率将会大大提高。

总共有N个数,如何判断第i+1个数到最后一个数之间有多少个数小于第i个数呢?不妨假设有一个区间 [1,N],只需要判断区间[i+1,N]之间有多少个数小于第i个数。如果我们把总区间初始化为0,然后把第i个数之前出现过的数都在相应的区间把它的值定为1,那么问题就转换成了[i+1,N]值的总和。再仔细想一下,区间[1,i]的值+区间[i+1,N]的值=区间[1,N]的值(i已经标记为1),所以区间[i+1,N]值的总和等于N-[1,i]的值!因为总共有N个数,不是比它小就是比它(大或等于)。

现在问题已经转化成了区间问题,枚举每个数,然后查询这个数前面的区间值的总和, i-[1,i] 既为逆序数。

线段树预处理时间复杂度O(NlogN),N次查询和N次插入的时间复杂度都为O(NlogN),总的时间复杂度O(3*NlogN)

树状数组不用预处理,N次查询和N次插入的时间复杂度都为O(NlogN),总的时间复杂度O(2*NlogN)

线段树:
 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// 线段树
#include <stdio .h>
#include <string .h>
#include <stdlib .h>
#define MAX 51000
#define MID(a,b) (a+b)>>1
#define R(a) (a< <1|1)
#define L(a) a<<1
typedef struct {
int num,left,right;
}Node;
int ans[MAX];
Node Tree[MAX<<2];
int n;

void Build(int t,int l,int r) //以1为根节点建立线段树
{
int mid;
Tree[t].left=l,Tree[t].right=r;
if(Tree[t].left==Tree[t].right)
{
Tree[t].num=0;
return ;
}
mid=MID(Tree[t].left,Tree[t].right);
Build(L(t),l,mid);
Build(R(t),mid+1,r);
}

void Insert(int t,int l,int r,int x) //向以1为根节点的区间[l,r]插入数字1
{
int mid;
if(Tree[t].left==l&&Tree[t].right==r)
{
Tree[t].num+=x;
return ;
}
mid=MID(Tree[t].left,Tree[t].right);
if(l>mid)
{
Insert(R(t),l,r,x);
}
else if(r< =mid)
{
Insert(L(t),l,r,x);
}
else
{
Insert(L(t),l,mid,x);
Insert(R(t),mid+1,r,x);
}
Tree[t].num=Tree[L(t)].num+Tree[R(t)].num;
}

int Query(int t,int l,int r) //查询以1为根节点,区间[l,r]的和
{
int mid;
if(Tree[t].left==l&&Tree[t].right==r)
return Tree[t].num;
mid=MID(Tree[t].left,Tree[t].right);
if(l>mid)
{
return Query(R(t),l,r);
}
else if(r<=mid)
{
return Query(L(t),l,r);
}
else
{
return Query(L(t),l,mid)+Query(R(t),mid+1,r);
}
}


int main()
{
int a,n,i,t;
scanf("%d",&t);
long long int k;
while(t--)
{
scanf("%d",&n);
memset(Tree,0,sizeof(Tree)); //初始化线段树
Build(1,1,n);
for(i=1;i<=n;i++) //输入n个数
{
scanf("%d",&ans[i]);
}
for(i=1,k=0;i<=n;i++)
{
a=ans[i];
Insert(1,a,a,1); //把线段树[ans[i],ans[i]]区间的值插入为1
k=k+(i-Query(1,1,a)); //查询区间[1,ans[i]]值的总和,逆序数等于i-[1,ans[i]]
}
printf("%lld\n",k);
}
return 0;
}

树状数组:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
// 树状数组
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define MAX 100010
int c[MAX],a[MAX],ans[MAX],n;

int Lowbit(int x) //返回二进制最后一个1所表示的数
{
return x&(-x);
}

void Updata(int x) //向前更新
{
while(x<=n)
{
c[x]++;
x+=Lowbit(x);
}
}

int Sum(int x) //向后更新求和
{
int sum=0;
while(x>0)
{
sum+=c[x];
x-=Lowbit(x);
}
return sum;
}

int main()
{
int i,t,k;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d",&ans[i]);
}
memset(c,0,sizeof(c)); //初始化树状数组
for(i=1,k=0;i<=n;i++)
{
Updata(ans[i]); //向后更新节点ans[i].k
k=k+(i-Sum(ans[i])); //向前查询节点ans[i].k
}
printf("%d\n",k);
}
return 0;
}

 

FFZU-ACM月赛不行了

线段树/树状数组的另一种用法不会,它的逆向问题更不会