T1
逃命
survive
Time Limit: 1 Sec Memory Limit: 32768 K
Description
糟糕的事情发生啦,现在大家都忙着逃命。但是逃命的通道很窄,大家只能排成一行。
现在有n个人,从1标号到n。同时有一些奇怪的约束条件,每个都形如:a必须在b之前。
同时,社会是不平等的,这些人有的穷有的富。1号最富,2号第二富,以此类推。有钱人就贿赂负责人,所以他们有一些好处。
负责人现在可以安排大家排队的顺序,由于收了好处,所以他要让1号尽量靠前,如果此时还有多种情况,就再让2号尽量靠前,如果还有多种情况,就让3号尽量靠前,以此类推。
那么你就要安排大家的顺序。我们保证一定有解。
Input
第一行一个整数T(1 <= T <= 5),表示测试数据的个数。
然后对于每个测试数据,第一行有两个整数n(1 <= n <= 30000)和m(1 <= m <= 100000),分别表示人数和约束的个数。
然后m行,每行两个整数a和b,表示有一个约束a号必须在b号之前。a和b必然不同。
Output
对每个测试数据,输出一行排队的顺序,用空格隔开。
Sample Input
1
5 10
3 5
1 4
2 5
1 2
3 4
1 4
2 3
1 5
3 5
1 2
Sample Output
1 2 3 4 5
题目来源:LOI队内互水(nue) 版权所有:vivym
正解:
这个题显然是个变化过之后的图论。
这个题不知道为什么当时就想到了拓扑,没错,这个题真的是拓扑。
但是,这个题要求序号小的尽量靠前,很容易想到的方法是把每一个限制(a在b前面)建成一条a到b的边,然后进行拓扑,先出来的在前面。
但是,这样做是不正确的。
当时为什么我忘记了~~好像随便给了个2 1 3 的数据就卡死了~~
正解是反向建图,然后拓扑,这样就会倒序存在一个数组里面了,再倒序输出就好了。
下面是vivym的std
1 #include <cstdio> 2 #include <queue> 3 #include <vector> 4 #include <cstring> 5 using namespace std; 6 7 const int maxn = 30000 + 5; 8 9 inline void scan(int &x) 10 { 11 char c; for(c = getchar();c < '0' || c > '9';c = getchar()); x = c - '0'; 12 for(c = getchar();c >= '0' && c <= '9';c = getchar()) x = (x << 1) + (x << 3) + c - '0'; 13 } 14 15 vector<int> G[maxn]; 16 int deg[maxn],N,M,ans[maxn],an; 17 18 inline void solve() 19 { 20 priority_queue<int> Q; 21 for(int i = 1;i <= N;i ++) if(!deg[i]) Q.push(i); 22 while(!Q.empty()) 23 { 24 int u = Q.top(); Q.pop(); 25 int sz = G[u].size(); 26 for(int i = 0;i < sz;i ++) 27 { 28 int v = G[u][i]; 29 if(-- deg[v] == 0) Q.push(v); 30 } 31 ans[an ++] = u; 32 } 33 } 34 35 int main() 36 { 37 freopen("survive.in","r",stdin); freopen("survive.out","w",stdout); 38 int T,u,v; scan(T); 39 while(T --) 40 { 41 an = 0; 42 memset(deg,0,sizeof deg); 43 scan(N),scan(M); 44 for(int i = 1;i <= N;i ++) G[i].clear(); 45 while(M --) scan(u),scan(v),G[v].push_back(u),deg[u] ++; 46 solve(); 47 for(int i = an - 1; i ;i --) printf("%d ",ans[i]); 48 printf("%d ",ans[0]); 49 } 50 return 0; 51 } 52 //by vivym
T2
递归数列
spp
Time Limit: 1 Sec Memory Limit: 256 MB
Description
一个由自然数组成的数列按下式定义:
对于i <= k:ai = bi
对于i > k: ai = c1ai-1 + c2ai-2 + ... + ckai-k
其中bj和 cj (1<=j<=k)是给定的自然数。写一个程序,给定自然数m <= n, 计算am + am+1 + am+2 + ... + an, 并输出它除以给定自然数p的余数的值。
Input
由四行组成。
第一行是一个自然数k。
第二行包含k个自然数b1, b2,...,bk。
第三行包含k个自然数c1, c2,...,ck。
第四行包含三个自然数m, n, p。
Output
仅包含一行:一个正整数,表示(am + am+1 + am+2 + ... + an) mod p的值。
Sample Input
2
1 1
1 1
2 10 1000003
Sample Output
142
HINT
对于100%的测试数据:
1<= k<=15
1 <= m <= n <= 10^18
我不会,看std吧。
1 #include <cstdio> 2 #include <cstring> 3 using namespace std; 4 5 typedef long long LL; 6 const int maxK = 15 + 2; 7 8 LL N,M,P; 9 10 struct Mat 11 { 12 LL a[maxK][maxK],n; 13 Mat(int n,LL x = 0) : n(n) { memset(a,0,sizeof(a)); for(int i = 0;i < n;i ++) a[i][i] = x; } 14 inline Mat operator * (const Mat &b) const 15 { 16 Mat c(n); 17 for(int i = 0;i < n;i ++) 18 for(int j = 0;j < n;j ++) 19 for(int k = 0;k < n;k ++) 20 (c.a[i][j] += (a[i][k] * b.a[k][j]) % P) %= P; 21 return c; 22 } 23 }; 24 25 inline Mat pow(Mat a,LL b) 26 { 27 Mat c(a.n,1); 28 for(; b ;b >>= 1) 29 { 30 if(b & 1) c = c * a; 31 a = a * a; 32 } 33 return c; 34 } 35 36 inline void scan(int &x) 37 { 38 char c; for(c = getchar();c < '0' || c > '9';c = getchar()); x = c - '0'; 39 for(c = getchar();c >= '0' && c <= '9';c = getchar()) x = (x << 1) + (x << 3) + c - '0'; 40 } 41 42 inline void scan(LL &x) 43 { 44 char c; for(c = getchar();c < '0' || c > '9';c = getchar()); x = c - '0'; 45 for(c = getchar();c >= '0' && c <= '9';c = getchar()) x = (x << 1) + (x << 3) + c - '0'; 46 } 47 48 int K; 49 LL B[maxK],C[maxK]; 50 51 inline LL getans(LL p) 52 { 53 Mat x(K + 1); LL sum = 0,ret = 0; 54 if(p <= K) 55 { 56 for(LL i = 0;i < p;i ++) (ret += B[i]) %= P; 57 return ret; 58 } 59 x.a[0][0] = 1; 60 for(int i = 1;i <= K;i ++) x.a[1][i] = x.a[0][i] = C[i - 1]; 61 for(int i = 2;i <= K;i ++) x.a[i][i - 1] = 1; 62 x = pow(x,p - K); 63 for(int i = 0;i < K;i ++) (sum += B[i]) %= P; 64 ret = (x.a[0][0] * sum) % P; 65 for(int i = 1;i <= K;i ++) (ret += x.a[0][i] * B[K - i] % P) %= P; 66 return ret; 67 } 68 69 int main() 70 { 71 freopen("spp.in","r",stdin); freopen("spp.out","w",stdout); 72 scan(K); 73 for(int i = 0;i < K;i ++) scan(B[i]); 74 for(int i = 0;i < K;i ++) scan(C[i]); 75 scan(M); scan(N); scan(P); 76 for(int i = 0;i < K;i ++) B[i] %= P,C[i] %= P; 77 printf("%lld",(getans(N) - getans(M - 1) + P) % P); 78 fclose(stdin); fclose(stdout); 79 return 0; 80 }