Categories
不学无术

Win8.1运行WinDbg调试出现"拒绝访问" | Kernel debugger failed initialization, Win32 error 0n5

恩,更新系统了之后就出现各种问题了…
主要症状是,打开虚拟机到Win2003的系统选择页面,然后开WinDbg,提示出错
Kernel debugger failed initialization, Win32 error 0n5
拒绝访问
查了半天弄了俩小时不知道啥原因,后来谷歌了一下,找到个类似的帖子
http://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/50c93600-6340-46e8-aa73-efa15ed41ba3/issue-with-setup-a-remote-kernel-debugging-session-using-firewireieee-1394
提示可能是权限问题…
然后我把WinDbg用管理员权限运行,尼玛就这样好了!!

Categories
不学无术

1063. Set Similarity (25)

时间限制:300ms
Given two sets of integers, the similarity of the sets is defined to be Nc/Nt*100%, where Nc is the number of distinct common numbers shared by the two sets, and Nt is the total number of distinct numbers in the two sets. Your job is to calculate the similarity of any given pair of sets.
Input Specification:
Each input file contains one test case. Each case first gives a positive integer N (<=50) which is the total number of sets. Then N lines follow, each gives a set with a positive M (<=104) and followed by M integers in the range [0, 109]. After the input of sets, a positive integer K (<=2000) is given, followed by K lines of queries. Each query gives a pair of set numbers (the sets are numbered from 1 to N). All the numbers in a line are separated by a space.
Output Specification:
For each query, print in one line the similarity of the sets, in the percentage form accurate up to 1 decimal place.
Sample Input:

3
3 99 87 101
4 87 101 5 87
7 99 101 18 5 135 18 99
2
1 2
1 3

Sample Output:

50.0%
33.3%

=====================================
这题目看起来挺简单,但是因为
1.数据量大
2.数值范围大
所以
1.要考虑求交集并集的最佳算法
2.不能用bitmap来用空间换时间
这个求交集并集(数量)的算法其实说来也不难,
有两个集合A,B,先假设
他们并集的大小uSize = |A|+|B|
交集的大小iSize = 0
集合进行排序(最小时间复杂度O(nlogn))后,可以用O(1)的算法找出并集交集:

A元素指针 ptrA = A.begin()
B元素指针 ptrB = B.begin()
while 列表A/B都没有遍历尽:
valA = *ptrA
valB = *ptrB
if valA == valB:
ptrA++
ptrB++
iSize ++
uSize -- #去掉多余的元素
elif valA > valB:
#数值小的往后挪动一格
ptrB++
else:
ptrA++

具体代码如下,后来想想其实用实现更方便一点:)

#include
#include
#include
using namespace std;
double getSimi(vector a, vector b)
{
vector *ptrA = &a;
vector *ptrB = &b;
if( a.size() > b.size())
{
//保证ptrA集合数目小
ptrB = &a;
ptrA = &b;
}
sort(ptrA->begin(), ptrA->end());
sort(ptrB->begin(), ptrB->end());
int iSize = 0;
int uSize = ptrB->size() + ptrA->size();
vector::iterator itA = ptrA->begin();
vector::iterator itB = ptrB->begin();
while(itA != ptrA->end() && itB!=ptrB->end())
{
long valA = *itA;
long valB = *itB;
if(valA == valB)
{
iSize ++;
uSize --;
itA++;
itB++;
}
else if(valA > valB)
{
//B队列下移一位
itB++;
}
else
{
//A队列下移一位
itA++;
}
}
return static_cast(iSize)/uSize;
}
int main()
{
int N;
scanf("%d", &N);
vector *arySets = new vector[N];
for(int i=0; i

测试点	结果	用时(ms)	内存(kB)	得分/满分
0	答案正确	0	720	12/12
1	答案正确	0	720	3/3
2	答案正确	0	790	3/3
3	答案正确	10	790	3/3
4	答案正确	260	990	4/4
Categories
不学无术

1062. Talent and Virtue (25)

About 900 years ago, a Chinese philosopher Sima Guang wrote a history book in which he talked about people’s talent and virtue. According to his theory, a man being outstanding in both talent and virtue must be a “sage(圣人)”; being less excellent but with one’s virtue outweighs talent can be called a “nobleman(君子)”; being good in neither is a “fool man(愚人)”; yet a fool man is better than a “small man(小人)” who prefers talent than virtue.
Now given the grades of talent and virtue of a group of people, you are supposed to rank them according to Sima Guang’s theory.
Input Specification:
Each input file contains one test case. Each case first gives 3 positive integers in a line: N (<=105), the total number of people to be ranked; L (>=60), the lower bound of the qualified grades — that is, only the ones whose grades of talent and virtue are both not below this line will be ranked; and H (<100), the higher line of qualification — that is, those with both grades not below this line are considered as the “sages”, and will be ranked in non-increasing order according to their total grades. Those with talent grades below H but virtue grades not are cosidered as the “noblemen”, and are also ranked in non-increasing order according to their total grades, but they are listed after the “sages”. Those with both grades below H, but with virtue not lower than talent are considered as the “fool men”. They are ranked in the same way but after the “noblemen”. The rest of people whose grades both pass the L line are ranked after the “fool men”.
Then N lines follow, each gives the information of a person in the format:

ID_Number Virtue_Grade Talent_Grade

where ID_Number is an 8-digit number, and both grades are integers in [0, 100]. All the numbers are separated by a space.
 
Output Specification:
The first line of output must give M (<=N), the total number of people that are actually ranked. Then M lines follow, each gives the information of a person in the same format as the input, according to the ranking rules. If there is a tie of the total grade, they must be ranked with respect to their virtue grades in non-increasing order. If there is still a tie, then output in increasing order of their ID’s.
Sample Input:

14 60 80
10000001 64 90
10000002 90 60
10000011 85 80
10000003 85 80
10000004 80 85
10000005 82 77
10000006 83 76
10000007 90 78
10000008 75 79
10000009 59 90
10000010 88 45
10000012 80 100
10000013 90 99
10000014 66 60

Sample Output:

12
10000013 90 99
10000012 80 100
10000003 85 80
10000011 85 80
10000004 80 85
10000007 90 78
10000006 83 76
10000005 82 77
10000002 90 60
10000014 66 60
10000008 75 79
10000001 64 90

======================================================
此题就是个分几类然后排序的问题,将每个人作为一个对象用STL就很好做了
重载一下运算符<就行了,STL的sort用它来排序的…
切记比较标准的(从C++基础教程上找到的)小于运算符重载的规范

bool operator<( const Object &obj) const;

没啥难度啦~就是有点费时间

#include
#include
#include
using namespace std;
struct Person
{
long id;
int talent;
int virtue;
Person(long _id, int _vir, int _tal)
{
id = _id;
talent = _tal;
virtue = _vir;
}
bool operator<( const Person& p) const { bool flag; //Overload operator < int total_self = talent + virtue; int total_him = p.talent + p.virtue; if(total_self < total_him) flag = true; else if(total_self > total_him)
flag = false;
else
{
if(virtue == p.virtue)
flag = id > p.id; //ID in increasin order!
else
flag = virtue < p.virtue; } return !flag; //Non-increasing order } }; int main() { vector people[4];
int N, L, H;
scanf("%d %d %d", &N, &L, &H);
int M = 0;
for(int i=0; i=H && vir >= H)
{
//Sage
people[0].push_back(p);
}
else if(vir >= H)
{
//Nobleman
people[1].push_back(p);
}
else if(vir >= tal)
{
//Fool
people[2].push_back(p);
}
else
{
//Small man
people[3].push_back(p);
}
}
printf("%dn", M);
for(int i=0; i<4; i++) { //Arrange them sort(people[i].begin(), people[i].end()); //Output for(vector::iterator it=people[i].begin(); it!=people[i].end(); it++)
{
printf("%ld %d %dn", it->id, it->virtue, it->talent);
}
}
return 0;
}

测试点	结果	用时(ms)	内存(kB)	得分/满分
0	答案正确	0	710	12/12
1	答案正确	0	710	2/2
2	答案正确	40	990	3/3
3	答案正确	80	3730	3/3
4	答案正确	80	3800	3/3
5	答案正确	0	790	2/2
Categories
不学无术

1061. Dating (20)

Sherlock Holmes received a note with some strange strings: “Let’s date! 3485djDkxh4hhGE 2984akDfkkkkggEdsb s&hgsfdk d&Hyscvnm”. It took him only a minute to figure out that those strange strings are actually referring to the coded time “Thursday 14:04” — since the first common capital English letter (case sensitive) shared by the first two strings is the 4th capital letter ‘D’, representing the 4th day in a week; the second common character is the 5th capital letter ‘E’, representing the 14th hour (hence the hours from 0 to 23 in a day are represented by the numbers from 0 to 9 and the capital letters from A to N, respectively); and the English letter shared by the last two strings is ‘s’ at the 4th position, representing the 4th minute. Now given two pairs of strings, you are supposed to help Sherlock decode the dating time.
Input Specification:
Each input file contains one test case. Each case gives 4 non-empty strings of no more than 60 characters without white space in 4 lines.
Output Specification:
For each test case, print the decoded time in one line, in the format “DAY HH:MM”, where “DAY” is a 3-character abbreviation for the days in a week — that is, “MON” for Monday, “TUE” for Tuesday, “WED” for Wednesday, “THU” for Thursday, “FRI” for Friday, “SAT” for Saturday, and “SUN” for Sunday. It is guaranteed that the result is unique for each case.
Sample Input:

3485djDkxh4hhGE
2984akDfkkkkggEdsb
s&hgsfdk
d&Hyscvnm

Sample Output:

THU 14:04

===========================================
题目看上去挺简单,自己做的时候粗心大意轻视了。
注意以下几点:
1.第一次比对的是从’A’-‘G’之内的相同字母,其他任何字符相同的无效
2.第二次比对的是从’0’-‘9’及’A’-‘N’之内的相同字符,其他无效
吐槽下第一次用VS2005感觉比VS2012差了好几条街,根本没有智能提示,估计是我变成习惯不好,编译错了N次…但是免研的时候估计没那么新版本,还是适应一下吧~
============================================

#include
#include
#include
using namespace std;
const char* wkdays[] = {"MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"};
int main()
{
const int BUFFER = 61;
char str1[BUFFER];
int results[3]; //存放四个数字结果
//第一次读取
cin >> str1;
int len1 = strlen(str1);
//第二次读取
char str2[BUFFER];
cin >> str2;
int len2 = strlen(str2);
int endIndex = (len1=7 ) //'G'
continue;
}
else
{
if(chrIndex < 0 || chrIndex >= 14) //'N'
{
if(digIndex <0 || digIndex >9)
continue;
digitFlag = true;//是个数字
}
}
if(str1[i] == str2[i])
{
if(firstTime)
{
results[0] = chrIndex;
firstTime = false;
}
else
{
results[1] = digitFlag? (digIndex):(chrIndex + 10);
break;
}
}
}
//第三次读取
char str3[BUFFER];
char str4[BUFFER];
cin >> str3 >> str4;
int len3 = strlen(str3);
int len4 = strlen(str4);
endIndex = (len3='a' && str3[i]<='z'; bool cond2 = str3[i]>='A' && str3[i]<='Z'; if(cond1 || cond2) { if(str3[i] == str4[i]) { results[2] = i; break; } } } cout << wkdays[results[0]] << " " << setw(2) << std::setfill('0') << results[1] << ":" << setw(2) << std::setfill('0') << results[2]; return 0; }

Categories
不学无术

1064. Complete Binary Search Tree (30)

时间限制
50 ms
内存限制
32000 kB
代码长度限制
16000 B

A Binary Search Tree (BST) is recursively defined as a binary tree which has the following properties:

  • The left subtree of a node contains only nodes with keys less than the node’s key.
  • The right subtree of a node contains only nodes with keys greater than or equal to the node’s key.
  • Both the left and right subtrees must also be binary search trees.

A Complete Binary Tree (CBT) is a tree that is completely filled, with the possible exception of the bottom level, which is filled from left to right.
Now given a sequence of distinct non-negative integer keys, a unique BST can be constructed if it is required that the tree must also be a CBT. You are supposed to output the level order traversal sequence of this BST.
Input Specification:
Each input file contains one test case. For each case, the first line contains a positive integer N (<=1000). Then N distinct non-negative integer keys are given in the next line. All the numbers in a line are separated by a space and are no greater than 2000.
Output Specification:
For each test case, print in one line the level order traversal sequence of the corresponding complete binary search tree. All the numbers in a line must be separated by a space, and there must be no extra space at the end of the line.
Sample Input:

10
1 2 3 4 5 6 7 8 9 0

Sample Output:

6 3 8 1 5 7 9 0 2 4

========================================
翻译过来就是…完全二叉搜索树
两个特征:二叉搜索树+完全二叉树
后面的代码里面可能有一点冗余的地方,就是那个if里面的,不过运行结果不影响,就没去改了。
我想的办法是自顶向下的,从一堆排好序的数中揪出那个“中间的”,然后分为两棵子树做,如此迭代(具体输出用<queue>的数组一层层弄就行了,这边懒得写):

function foo:
本行完整的应有m = log2(N)个
本行多出的有r = N – m个 (就是完全树的最底下一行多余的节点数)
if r==0:
太完美了..将中间的数找出,放入输出队列中
else:
最后一排填满的话会有k=2^m个元素
那么左右边分开的话,各有k/2个
这样就能算出左边右边应该有多少个元素“多余”,去除左右边多余的剩下就是真正的长度
去除多余的元素,根据长度找出中间的元素,放入输出队列
递归接着算

=======================================================================

#include
#include /* qsort */
#include
#include
using namespace std;
int compare(const void *a, const void *b)
{
return ( *(int*)a - *(int*)b);
}
queue *results;
void run(int* srcAry, int fromIndex, int toIndex, int level)
{
int length = toIndex - fromIndex + 1;
if(length < 1) return; if(length == 1) { //到底了 //printf("%d ", srcAry[fromIndex]); results[level].push(srcAry[fromIndex]); return; } int m = log((double)length)/log((double)2); int r = length - pow(2.0f,m) + 1; if(r == 0) { int midIndex = fromIndex + length/2; //printf("%d ", srcAry[midIndex]); results[level].push(srcAry[midIndex]); run(srcAry, fromIndex, midIndex-1, level-1); run(srcAry, midIndex+1, toIndex, level-1); } else { int k = pow(2.0f, m); int left = k/2, right = k/2; if(r <= left) { //只有左边有 left = r; right = 0; } else { //右边也有 right = r - left; } int restLength = length - r; int midIndex = fromIndex + left + restLength/2; //printf("%d ", srcAry[midIndex]); results[level].push(srcAry[midIndex]); run(srcAry, fromIndex, midIndex -1, level-1); run(srcAry, midIndex+1, toIndex, level-1); } } int main() { int N; scanf("%d", &N); int *ary = new int[N]; for(int i=0; i[level +1];
run(ary, 0, N-1, level);
int count = 1;
level++;
while (level--)
{
queue q = results[level];
while(!q.empty())
{
printf("%d", q.front());
if(count < N) printf(" "); count ++; q.pop(); } } return 0; }

 

Categories
不学无术

HDOJ1005 Number Sequence

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 84538    Accepted Submission(s): 20059

Problem Description
A number sequence is defined as follows:f(1) = 1, f(2) = 1, f(n) = (A * f(n – 1) + B * f(n – 2)) mod 7.
Given A, B, and n, you are to calculate the value of f(n).

 

Input
The input consists of multiple test cases. Each test case contains 3 integers A, B and n on a single line (1 <= A, B <= 1000, 1 <= n <= 100,000,000). Three zeros signal the end of input and this test case is not to be processed.

 

Output
For each test case, print the value of f(n) on a single line.

 

Sample Input
1 1 3 1 2 10 0 0 0

 

Sample Output
2 5

 
===========================================
按照PPT里面的说法,就是“对于这种题目,千万不能蛮干!实际上,有经验的同学看到本题目的数据规模,很快就能知道:这类题目有规律可循。”
由于是mod7的关系,函数f两个参数,都是0~6范围内的,所以共计7*7=49种可能性,这是其一,避免重复计算。
其二,http://www.cnblogs.com/Lyush/archive/2011/09/04/2165927.html里面所说一般,这种东西肯定是有循环的,循环节最大50,何时找到循环呢?两个参数一样的时候呗。这个问题困扰了我一晚上,今天早上实在忍不住搜博客搜到了…所以自己还是太年轻了吧
这两点搞定了,就没有任何问题了。

#include 
using namespace std;
int f(int A, int B, unsigned long n)
{
    if(n == 2 || n == 1)
        return 1;
    int mat[7][7];
    int looked[7][7];
    for(int i=0; i<7; i++)
    {
        for(int j=0; j<7; j++)
        {
            mat[i][j] = (A*i+B*j)%7;
            looked[i][j] = 0;
        }
    }
    int last_2 = 1;
    int last_1 = 1;
    looked[1][1] = 2;
    unsigned long next = n;
    for(unsigned long m=3; m<=next; m++)
    {
        int curr = mat[last_1][last_2];
        last_2 = last_1;
        last_1 = curr;
        if(looked[last_1][last_2] > 0)
        {
            //开始循环了!
            next = (n - looked[last_1][last_2])%(m - looked[last_1][last_2]) + m;
        }
        looked[last_1][last_2] = m;
    }
    return last_1;
}
int main()
{
    int A, B;
    unsigned long n;
    while(cin >> A >> B >> n && A+B+n != 0)
    {
        cout << f(A, B, n) << endl;
    }
    return 0;
}
Categories
不学无术

1059. Prime Factors (25)

Given any positive integer N, you are supposed to find all of its prime factors, and write them in the format N = p1^k1* p2^k2 *…*pm^km.
Input Specification:
Each input file contains one test case which gives a positive integer N in the range of long int.
Output Specification:
Factor N in the format N = p1^k1 * p2^k2 *…*pm^km, where pi‘s are prime factors of N in increasing order, and the exponent ki is the number of pi — hence when there is only one pi, ki is 1 and must NOT be printed out.
Sample Input:

97532468

Sample Output:

97532468=2^2*11*17*101*1291

 
=======================================================
就是一个找质数的问题,其实很简单啦~
切记从小的这头开始尝试,因为试想一下,除掉2,3这种小数字之后,需要尝试的明显少了N多!

#include 
#include 
using namespace std;
const 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 };
const int prime_length = 25;
map primeMap;
bool isPrime(long val)
{
    for(int i=0; i 0)
        return primeMap[val];
    //没办法了只能苦算
    for(long x=val/2; x>1; x--)
    {
        if(val%x == 0)
        {
            //合数
            primeMap.insert(pair(val, false));
            return false;
        }
    }
    primeMap.insert(pair(val, true));
    return true;
}
map factorCountMap;  //<素数,指数>
int main()
{
    long input;
    scanf("%ld", &input);
    printf("%ld=", input);
    //
    if(input == 1)
    {
        printf("1");
        return 0;
    }
    //从2开始计算...
    long divisor = 2;
    while(input > 1)
    {
        if(!isPrime(divisor))
        {
            divisor++;
            continue;
        }
        if(input%divisor == 0)
        {
            //有这个素数因子
            if(factorCountMap.count(divisor) > 0)
            {
                factorCountMap[divisor] = factorCountMap[divisor] + 1;
            }
            else
            {
                factorCountMap[divisor] = 1;
            }
            input /= divisor;
        }
        else
            divisor++;
    }
    map::iterator it = factorCountMap.begin();
    for(; it!=factorCountMap.end(); it++)
    {
        if(it != factorCountMap.begin())
            printf("*");
        pair p = *it;
        long factor = p.first;
        long exponent = p.second;
        printf("%ld", factor);
        if(exponent > 1)
            printf("^%ld", exponent);
    }
    return 0;
}
Categories
不学无术

1011. World Cup Betting (20)

With the 2010 FIFA World Cup running, football fans the world over were becoming increasingly excited as the best players from the best teams doing battles for the World Cup trophy in South Africa. Similarly, football betting fans were putting their money where their mouths were, by laying all manner of World Cup bets.
Chinese Football Lottery provided a “Triple Winning” game. The rule of winning was simple: first select any three of the games. Then for each selected game, bet on one of the three possible results — namely W for win, T for tie, and L for lose. There was an odd assigned to each result. The winner’s odd would be the product of the three odds times 65%.
For example, 3 games’ odds are given as the following:

 W    T    L
1.1  2.5  1.7
1.2  3.0  1.6
4.1  1.2  1.1

To obtain the maximum profit, one must buy W for the 3rd game, T for the 2nd game, and T for the 1st game. If each bet takes 2 yuans, then the maximum profit would be (4.1*3.0*2.5*65%-1)*2 = 37.98 yuans (accurate up to 2 decimal places).
Input
Each input file contains one test case. Each case contains the betting information of 3 games. Each game occupies a line with three distinct odds corresponding to W, T and L.
Output
For each test case, print in one line the best bet of each game, and the maximum profit accurate up to 2 decimal places. The characters and the number must be separated by one space.
Sample Input

1.1 2.5 1.7
1.2 3.0 1.6
4.1 1.2 1.1

Sample Output

T T W 37.98

============================================================
史上最简单的一道题,直接放代码…

#include 
#include  // std::setprecision
using namespace std;
int main()
{
    float best_odds[3] = {0.0, 0.0, 0.0};
    char mark[3] = {'W','T','L'};
    char best_mark[4] = {' ',' ',' '};
    float result = 1.0;
    for(int i=0; i<3; i++)
    {
        for(int j=0; j<3; j++)
        {
            float temp;
            cin >> temp;
            if(temp > best_odds[i])
            {
                best_odds[i] = temp;
                best_mark[i] = mark[j];
            }
        }
        result *= best_odds[i];
        char out = best_mark[i];
        cout << out << " ";
    }
    result = (result * 0.65 - 1) * 2;
    cout << fixed << setprecision(2) << result;
    return 0;
}
Categories
不学无术

ZOJ Problem Set – 1002

原题:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1002
试水ZOJ的第一题,果然ACM的难度比PAT大一些,入门题目都那么长…
思路其实不难,弄个二维数组来搞,有点回溯的味道,刚巧最近看书看到了分而治之还要动态规划什么的
某一步的结果= max{当前位置放置1个+后面位置放置个数, 当前位置放置0个+后面位置放置个数}
然后就能做啦~
 

#include 
#include 
#include 
#include     // std::max
using namespace std;
enum state{
    READY, BLOCK, DISABLED, USED
};
/**
从i,j 开始找下一个可用的位置
**/
void findNextPossiblePos(int &i, int &j, int **inData, int N)
{
    for(int m=i; m=0; row--)
    {
        if(s1Data[row][j] == BLOCK)
            break;
        s1Data[row][j]= DISABLED;
    }
    //↓
    for(int row = i+1; row=0; col--)
    {
        if(s1Data[i][col] == BLOCK)
            break;
        s1Data[i][col] = DISABLED;
    }
    //→
    for(int col = j+1; cols2Result)? s1Result:s2Result;
    //mmax[i][j] = retVal;
    return retVal;
}
int main()
{
    int n;
    while(cin >> n)
    {
        if(n == 0)
            break;
        //create data
        int **data = new int*[n];
        for(int i=0; i> c;
                if(c == '.')
                    data[i][j] = READY;
                else if(c == 'X')
                    data[i][j] = BLOCK;
                else
                    data[i][j] = DISABLED;
            }
        }
        /////Start!
        int result = startJob(data, n, 0, 0);
        cout << result << endl;
    }
    return 0;
}
Categories
不学无术

1053. Path of Equal Weight (30)

原题链接:http://pat.zju.edu.cn/contests/pat-a-practise/1053
这道题目就是个树的遍历,反正树嘛可以好多方法构造的…我这边就给了个map实现,其实用数组也是完全可以的嘛:)
然后不管用DFS,BFS还是神马遍历一下整棵树就出来了…
能继续使用的在working里面,有结果的在result里面
一开始working集合放一个根节点的Path
注意特殊情况:只有根节点一个节点的时候….
其他没啥特别的,原以为10ms时间很短,做出来才发现其实都是0ms搞定的:)
另外另外,//掉的结构内的运算符重载,VS2013可以运行,但是PAT出现编译错误,貌似是linux下严格一些的吧,省事儿就改成了外面自定义比较函数了。据查,结构体内搞个友元函数然后结构体外面写实现也是可以的…不过这样好麻烦
 

#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
int *weight;
struct Path
{
    list path;
    long currWt;
    Path()
    {
        currWt = 0;
    }
    ////重载运算符实现sort
    //bool operator <(const Path& p2)
    //{
    //    list::const_iterator it1 = path.begin();
    //    list::const_iterator it2 = p2.path.begin();
    //    while(it1 != path.end() && it2 != p2.path.end())
    //    {
    //        int id1 = *it1;
    //        int wt1 = weight[id1];
    //        int id2 = *it2;
    //        int wt2 = weight[id2];
    //        if(wt2 > wt1)
    //            return false;
    //        else if(wt2 < wt1)
    //            return true;
    //        it1 ++;
    //        it2 ++;
    //    }
    //    return false;
    //}
};
bool compare (Path x, Path y)
{
    list::const_iterator it1 = x.path.begin();
        list::const_iterator it2 = y.path.begin();
        while(it1 != x.path.end() && it2 != y.path.end())
        {
            int id1 = *it1;
            int wt1 = weight[id1];
            int id2 = *it2;
            int wt2 = weight[id2];
            if(wt2 > wt1)
                return false;
            else if(wt2 < wt1)
                return true;
            it1 ++;
            it2 ++;
        }
        return false;
}
#define PAIR pair<int, vector>
int main()
{
    int N, M;
    long S;
    scanf("%d %d %ld", &N, &M, &S);
    weight = new int[N]; //weights
    bool *isLeaf = new bool[N];
    for(int i=0; i<N; i++)
        isLeaf[i] = true;
    map<int, vector> tree;
    vector results;
    vector working;
    for(int i=0; i<N; i++)
    {
        //read weight
        scanf("%d", &weight[i]);
    }
    for(int i=0; i<M; i++)
    {
        //read link info
        int nodeid;
        int K;
        scanf("%d %d", &nodeid, &K);
        isLeaf[nodeid] = false;
        vector linkedNodes;
        while(K--)
        {
            int dst;
            scanf("%d", &dst);
            linkedNodes.push_back(dst);
        }
        tree.insert(PAIR(nodeid, linkedNodes));
    }
    ///////////////////////////////
    //BFS root id = 00
    int wt_root = weight[0]; //根节点的权重
    Path path;
    path.currWt  = wt_root;
    path.path.push_back(0);
    working.push_back(path);
    while(!working.empty())
    {
        Path path = working.front(); //取最顶上一个操作
        int lastNode = path.path.back();
        int currWt = path.currWt; //当前的权重
        if(currWt == S)
        {
            //刚好了已经..(根节点就满足))
            results.push_back(path);
            working.erase(working.begin());
            continue;
        }
        vector linkedNodes = tree[lastNode];
        vector::iterator it;
        for(it = linkedNodes.begin(); it!=linkedNodes.end(); it++)
        {
            //遍历所有子节点
            int id = *it;
            int wt_till_this = weight[id] + currWt;//加上之后的权重
            if(wt_till_this > S)
                continue; //已经超过了
            else if(wt_till_this == S)
            {
                //刚好,加入result集合
                //如果还没到叶节点,那么它也不是答案!
                if(!isLeaf[id])
                    continue;
                Path newPath = path;
                newPath.currWt = wt_till_this;
                newPath.path.push_back(id);
                results.push_back(newPath);
            }
            else
            {
                //虽然还是小了,但是有希望
                Path newPath = path;
                newPath.currWt = wt_till_this;
                newPath.path.push_back(id);
                working.push_back(newPath);
            }
        }
        //使用完了之后,删掉这个
        working.erase(working.begin());
    }
    ///////////////////////////////
    //SORT
    sort(results.begin(), results.end(), compare);
    ///////////////////////////////
    //OUTPUT
    vector::iterator it;
    for(it = results.begin(); it != results.end(); it++)
    {
        Path p = *it;
        list::iterator iter;
        for(iter = p.path.begin(); iter != p.path.end(); iter++)
        {
            int id = *iter;
            int wt = weight[id];
            if(iter != p.path.begin())
                printf(" ");
            printf("%d", wt);
        }
        printf("n");
    }
    return 0;
}