2017 icpc 沈阳网络赛

cable cable cable

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 278    Accepted Submission(s): 224


Problem Description
Connecting the display screen and signal sources which produce different color signals by cables, then the display screen can show the color of the signal source.Notice that every signal source can only send signals to one display screen each time.
Now you have M display screens and K different signal sources(KM2321 ). Select K display screens from M display screens, how many cables are needed at least so that **any** K display screens you select can show exactly K different colors.
 

 

Input
Multiple cases (no more than 100 ), for each test case:
there is one line contains two integers M and K .
 

 

Output
Output the minimum number of cables N .
 

 

Sample Input
3 2 20 15
 

 

Sample Output
4 90
Hint
As the picture is shown, when you select M1 and M2, M1 show the color of K1, and M2 show the color of K2. When you select M3 and M2, M2 show the color of K1 and M3 show the color of K2. When you select M1 and M3, M1 show the color of K1.
 

 

Source
 

 

Recommend
liuyiding   |   We have carefully selected several similar problems for you:  6205 6204 6203 6202 6201 
 

 
在所有m个显示屏中选出k个,和光源有唯一连线。然后剩下(m-k)个显示屏都和k个光源都有连线,那么就保证无论怎么选都能有k种不同颜色。
于是方案数=k+(m-k)*k=k*(m-k+1)。
 1 #include<bits/stdc++.h>
 2 #define clr(x) memset(x,0,sizeof(x))
 3 #define clr_1(x) memset(x,-1,sizeof(x))
 4 #define LL long long
 5 #define mod 998244353
 6 using namespace std;
 7 const int N=1e5+10;
 8 LL n,m,k;
 9 int main()
10 {
11     while(scanf("%lld%lld",&n,&k)!=EOF)
12     {
13         printf("%lld\n",k*(n-k+1));
14     }
15     return 0;
16 }
View Code

 

array array array

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 444    Accepted Submission(s): 275


Problem Description
One day, Kaitou Kiddo had stolen a priceless diamond ring. But detective Conan blocked Kiddo's path to escape from the museum. But Kiddo didn't want to give it back. So, Kiddo asked Conan a question. If Conan could give a right answer, Kiddo would return the ring to the museum.
Kiddo: "I have an array A and a number k , if you can choose exactly k elements from A and erase them, then the remaining array is in non-increasing order or non-decreasing order, we say A is a magic array. Now I want you to tell me whether A is a magic array. " Conan: "emmmmm..." Now, Conan seems to be in trouble, can you help him?
 

 

Input
The first line contains an integer T indicating the total number of test cases. Each test case starts with two integers n and k in one line, then one line with n integers: A1,A2An .
1T20
1n105
0kn
1Ai105
 

 

Output
For each test case, please output "A is a magic array." if it is a magic array. Otherwise, output "A is not a magic array." (without quotes).
 

 

Sample Input
3 4 1 1 4 3 7 5 2 4 1 3 1 2 6 1 1 4 3 5 4 6
 

 

Sample Output
A is a magic array. A is a magic array. A is not a magic array.
 

 

Source
 

 

Recommend
liuyiding   |   We have carefully selected several similar problems for you:  6205 6204 6203 6202 6201 

 
最长非递减子序列的模板题。数列从头到尾和从尾到头都来一遍。每次查询的是以a[i]结尾的序列的最长长度,更新的是a[i]这个位置点的最长长度。用树状数组更新和查询最大值就好了。
 1 #include<bits/stdc++.h>
 2 #define clr(x) memset(x,0,sizeof(x))
 3 #define clr_1(x) memset(x,-1,sizeof(x))
 4 #define LL long long
 5 #define mod 998244353
 6 using namespace std;
 7 const int N=1e5+10;
 8 int  n,m,k,t;
 9 int a[N],bit[N],maxn;
10 int maxed(int i)
11 {
12     int s=0;
13     while(i>0)
14     {
15         s=max(bit[i],s);
16         i-=i&-i;
17     }
18     return s;
19 }
20 void add(int i,int x)
21 {
22     while(i<N)
23     {
24         bit[i]=max(bit[i],x);
25         i+=i&-i;
26     }
27     return ;
28 
29 }
30 int main()
31 {
32     int  T;
33     scanf("%d",&T);
34     while(T--)
35     {
36         scanf("%d%d",&n,&k);
37         for(int i=1;i<=n;i++)
38         {
39             scanf("%d",&a[i]);
40         }
41         clr(bit);
42         maxn=0;
43         for(int i=1;i<=n;i++)
44         {
45             t=maxed(a[i])+1;
46             if(t>maxn)
47                 maxn=t;
48             add(a[i],t);
49         }
50         clr(bit);
51         for(int i=n;i>=1;i--)
52         {
53             t=maxed(a[i])+1;
54             if(t>maxn)
55                 maxn=t;
56             add(a[i],t);
57         }
58         if(n-k<=maxn)
59             printf("A is a magic array.\n");
60         else
61             printf("A is not a magic array.\n");
62     }
63     return 0;
64 }
View Code

 

number number number

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 390    Accepted Submission(s): 247


Problem Description
We define a sequence F :

F0=0,F1=1 ;
Fn=Fn1+Fn2 (n2) .

Give you an integer k , if a positive number n can be expressed by
n=Fa1+Fa2+...+Fak where 0a1a2ak , this positive number is mjfgood . Otherwise, this positive number is mjfbad .
Now, give you an integer k , you task is to find the minimal positive mjfbad number.
The answer may be too large. Please print the answer modulo 998244353.
 

 

Input
There are about 500 test cases, end up with EOF.
Each test case includes an integer k which is described above. (1k109 )
 

 

Output
For each case, output the minimal mjfbad number mod 998244353.
 

 

Sample Input
1
 

 

Sample Output
4
 

 

Source
 

fibonicci数列:1,1,2,3,5,8,13,21,34,55,89,144,233.....
打个表发觉对应各个k下的数为:4=1+3,12=4+8,33=12+21,88=33+55,232=88+144......
可以发现选k个数的fbonicci数列数集中没出现的最小整数f[i]=f[i-1]+fib[(i+1)*2];
于是写个3*3的矩阵快速幂同时加速fib与f[i]的运算就好了。
 1 #include<bits/stdc++.h>
 2 #define clr(x) memset(x,0,sizeof(x))
 3 #define LL long long
 4 #define mod 998244353
 5 using namespace std;
 6 typedef vector<LL> vec;
 7 typedef vector<vec> mat;
 8 mat ori(1,vec(3)),orip(1,vec(3));
 9 mat mart(3,vec(3)),martp(3,vec(3));
10 mat mul(const mat &a,const mat &b)
11 {
12     int row=a.size();
13     int col=b[0].size();
14     int mid=b.size();
15     mat c(row,vec(col));
16     for(int i=0;i<row;i++)
17         for(int j=0;j<col;j++)
18             for(int k=0;k<mid;k++)
19                 c[i][j]=(c[i][j]+a[i][k]*b[k][j]%mod)%mod;
20     return c;
21 }
22 mat quick_pow(mat a,LL n)
23 {
24     int len=a.size();
25     mat res(len,vec(len));
26     for(int i=0;i<len;i++)
27         res[i][i]=1;
28     while(n)
29     {
30         if(n&1)
31             res=mul(res,a);
32         a=mul(a,a);
33         n>>=1;
34     }
35     return res;
36 }
37 void init()
38 {
39     orip[0][0]=8;
40     orip[0][1]=5;
41     orip[0][2]=4;
42     martp[0][0]=2;
43     martp[0][1]=1;
44     martp[0][2]=1;
45     martp[1][0]=1;
46     martp[1][1]=1;
47     martp[2][2]=1;
48     return ;
49 }
50 int main()
51 {
52     LL n,m;
53     init();
54     while(scanf("%lld",&n)!=EOF)
55     {
56         ori=orip;
57         mart=martp;
58         mart=quick_pow(mart,n-1);
59         ori=mul(ori,mart);
60         printf("%lld\n",ori[0][2]);
61     }
62     return 0;
63 }
View Code

 

transaction transaction transaction

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others)
Total Submission(s): 877    Accepted Submission(s): 431


Problem Description
Kelukin is a businessman. Every day, he travels around cities to do some business. On August 17th, in memory of a great man, citizens will read a book named "the Man Who Changed China". Of course, Kelukin wouldn't miss this chance to make money, but he doesn't have this book. So he has to choose two city to buy and sell.
As we know, the price of this book was different in each city. It is ai yuan in i t city. Kelukin will take taxi, whose price is 1 yuan per km and this fare cannot be ignored.
There are n1 roads connecting n cities. Kelukin can choose any city to start his travel. He want to know the maximum money he can get.
 

 

Input
The first line contains an integer T (1T10 ) , the number of test cases.
For each test case:
first line contains an integer n (2n100000 ) means the number of cities;
second line contains n numbers, the i th number means the prices in i th city; (1Price10000)
then follows n1 lines, each contains three numbers x , y and z which means there exists a road between x and y , the distance is z km (1z1000) .
 

 

Output
For each test case, output a single number in a line: the maximum money he can get.
 

 

Sample Input
1 4 10 40 15 30 1 2 30 1 3 2 3 4 10
 

 

Sample Output
8
 

 

Source
将此题分为两部分求解。一部分是以点u为lca的买书和过路的花费最小值leftmin。这部分可以用dfso(n)做出来,将子节点leftmin+路径花费和当前节点的花费(也就是当前节点买书)中较小者作为当前点leftmin,这个可以通过dfs回溯,在每个点o(子节点数目)解决,总的来说是访问每个点o(n)+子节点回溯o(n-1)的时间,也就是o(n)。然后求其他点到该点u的最小花费,显然该点花费-最小花费是该点可获得的最大利益。这个同样可以用一个dfs在o(n)的时间内解决。不排除常数的话差不多是3n的时间能解决该问题.
 1 #include<bits/stdc++.h>
 2 #define clr(x) memset(x,0,sizeof(x))
 3 #define clr_1(x) memset(x,-1,sizeof(x))
 4 #define LL long long
 5 #define mod 998244353
 6 using namespace std;
 7 const int N=1e5+10;
 8 int T;
 9 int n,m,u,v;
10 LL a[N],ck,maxn,ans,leftmin[N],allmin[N];
11 struct edg
12 {
13     int next,to;
14     LL val;
15 }edge[N*2];
16 int head[N],ecnt,cnt;
17 void addedge(int u,int v,LL val)
18 {
19     edge[++ecnt]=(edg){head[u],v,val};
20     head[u]=ecnt;
21     return ;
22 }
23 void dfs(int u,int pre,LL val)
24 {
25     leftmin[u]=a[u];
26     for(int i=head[u];i!=-1;i=edge[i].next)
27     {
28         if(edge[i].to!=pre)
29         {
30             dfs(edge[i].to,u,edge[i].val);
31             leftmin[u]=min(leftmin[edge[i].to]+edge[i].val,leftmin[u]);
32         }
33     }
34     return ;
35 }
36 void dfs2(int u,int pre,LL val)
37 {
38     allmin[u]=min(allmin[pre]+val,leftmin[u]);
39     maxn=max(maxn,a[u]-allmin[u]);
40     for(int i=head[u];i!=-1;i=edge[i].next)
41     {
42         if(edge[i].to!=pre)
43         {
44             dfs2(edge[i].to,u,edge[i].val);
45         }
46     }
47     return ;
48 }
49 int main()
50 {
51     int T;
52     scanf("%d",&T);
53     while(T--)
54     {
55         scanf("%d",&n);
56         clr_1(head);
57         ecnt=cnt=0;
58         ans=maxn=0;
59         for(int i=1;i<=n;i++)
60             scanf("%lld",&a[i]);
61         for(int i=1;i<n;i++)
62         {
63             scanf("%d%d%lld",&u,&v,&ck);
64             addedge(u,v,ck);
65             addedge(v,u,ck);
66         }
67         allmin[1]=0x3f3f3f3f;
68         dfs(1,1,0);
69         dfs2(1,1,0);
70         printf("%lld\n",maxn);
71     }
72     return 0;
73 }
View Code

 

card card card

Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1100    Accepted Submission(s): 487


Problem Description
As a fan of Doudizhu, WYJ likes collecting playing cards very much.
One day, MJF takes a stack of cards and talks to him: let's play a game and if you win, you can get all these cards. MJF randomly assigns these cards into n heaps, arranges in a row, and sets a value on each heap, which is called "penalty value".
Before the game starts, WYJ can move the foremost heap to the end any times.
After that, WYJ takes the heap of cards one by one, each time he needs to move all cards of the current heap to his hands and face them up, then he turns over some cards and the number of cards he turned is equal to the penaltyvalue .
If at one moment, the number of cards he holds which are face-up is less than the penaltyvalue , then the game ends. And WYJ can get all the cards in his hands (both face-up and face-down).
Your task is to help WYJ maximize the number of cards he can get in the end.So he needs to decide how many heaps that he should move to the end before the game starts. Can you help him find the answer?
MJF also guarantees that the sum of all "penalty value" is exactly equal to the number of all cards.
 

 

Input
There are about 10 test cases ending up with EOF.
For each test case:
the first line is an integer n (1n106 ), denoting n heaps of cards;
next line contains n integers, the i th integer ai (0ai1000 ) denoting there are ai cards in i th heap;
then the third line also contains n integers, the i th integer bi (1bi1000 ) denoting the "penalty value" of i th heap is bi .
 

 

Output
For each test case, print only an integer, denoting the number of piles WYJ needs to move before the game starts. If there are multiple solutions, print the smallest one.
 

 

Sample Input
5 4 6 2 8 4 1 5 7 9 2
 

 

Sample Output
4
Hint
[pre] For the sample input: + If WYJ doesn't move the cards pile, when the game starts the state of cards is: 4 6 2 8 4 1 5 7 9 2 WYJ can take the first three piles of cards, and during the process, the number of face-up cards is 4-1+6-5+2-7. Then he can't pay the the "penalty value" of the third pile, the game ends. WYJ will get 12 cards. + If WYJ move the first four piles of cards to the end, when the game starts the state of cards is: 4 4 6 2 8 2 1 5 7 9 WYJ can take all the five piles of cards, and during the process, the number of face-up cards is 4-2+4-1+6-5+2-7+8-9. Then he takes all cards, the game ends. WYJ will get 24 cards. It can be improved that the answer is 4. **huge input, please use fastIO.** [/pre]
 
题意比较难读懂的水题。。。我第一个开的就是这题,反正你们对着xx翻译看吧。。。看完就知道了。。。
要写个读入加速就对了。
 1 #include<bits/stdc++.h>
 2 #define clr(x) memset(x,0,sizeof(x))
 3 #define clr_1(x) memset(x,-1,sizeof(x))
 4 #define mod 1000000007
 5 using namespace std;
 6 const int N=1e6+10;
 7 typedef long long LL;
 8 inline void getInt(LL* p) {
 9     char ch;
10     do {
11         ch = getchar();
12     } while (ch == ' ' || ch == '\n');
13     if (ch == '-') {
14         *p = -(getchar() - '0');
15         while ((ch = getchar()) >= '0' && ch <= '9') {
16             *p = *p * 10 - ch + '0';
17         }
18     }
19     else {
20         *p = ch - '0';
21         while ((ch = getchar()) >= '0' && ch <= '9') {
22             *p = *p * 10 + ch - '0';
23         }
24     }
25 }
26 LL a[N],b[N],ans,maxn,lz,num;
27 int n,m,T,pos,prepos,rpos;
28 int main()
29 {
30     while(scanf("%d",&n)!=EOF)
31     {
32         for(int i=1;i<=n;i++)
33         {
34             getInt(&a[i]);
35         }
36         for(int i=1;i<=n;i++)
37         {
38             getInt(&b[i]);
39         }
40         maxn=0;
41         ans=0;
42         num=0;
43         prepos=0;
44         pos=0;
45         rpos=0;
46         for(int i=1;i<=n;i++)
47         {
48             ans+=a[i]-b[i];
49             num+=a[i];
50             if(ans<0)
51             {
52                 prepos=pos;
53                 pos=i;
54                 if(num>maxn)
55                 {
56                     rpos=prepos;
57                     maxn=num;
58                 }
59                 ans=0;
60                 num=0;
61             }
62         }
63         for(int i=1;i<=n;i++)
64         {
65             ans+=a[i]-b[i];
66             num+=a[i];
67             if(ans<0)
68             {
69                 prepos=pos;
70                 pos=i;
71                 if(num>maxn)
72                 {
73                     rpos=prepos;
74                     maxn=num;
75                 }
76                 ans=0;
77                 num=0;
78                 if(prepos<=pos) break;
79             }
80             if(pos==i)
81             {
82                 rpos=pos;
83                 break;
84             }
85         }
86         printf("%d\n",rpos);
87     }
88     return 0;
89 }
View Code

 

string string string

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1452    Accepted Submission(s): 416


Problem Description
Uncle Mao is a wonderful ACMER. One day he met an easy problem, but Uncle Mao was so lazy that he left the problem to you. I hope you can give him a solution.
Given a string s, we define a substring that happens exactly k times as an important string, and you need to find out how many substrings which are important strings.
 

 

Input
The first line contains an integer T (T100) implying the number of test cases.
For each test case, there are two lines:
the first line contains an integer k (k1) which is described above;
the second line contain a string s (length(s)105).
It's guaranteed that length(s)2106.
 

 

Output
For each test case, print the number of the important substrings in a line.
 

 

Sample Input
2 2 abcabc 3 abcabcabcabc
 

 

Sample Output
6 9
 
这题是不同长度串和长度为k的串的总数的综合体。k=1统计的是该字符串不同的子串的个数,k>1统计的是该字符串出现恰好k次的子串个数。k=1论文题,无需赘言。
k>1的话我们遍历一遍sa数组,每次选位置p开始的连续k个字符串,求出他们最长公共前缀,该前缀任何前缀大于等于k次的前缀。那么我们再算出该前缀中大于k次的前缀,减掉就好了。这大于k次的前缀的长度是p-1~p+k和p~p+k+1中最长公共前缀较大者,但不超过连续k串最长公共前缀的长度。这些都能由height解决。上述操作就是height中就是找连续k-1个里的最小值,然后找p-1和p+1中较大值,若(最小值-较大值)<=0说明这连续k串都大于k次,对答案没贡献。否则有(最小值-较大值)串是正好出现k次的。我用mutiset动态存储height,效果很不错。
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<set>
 6 #define clr(x) memset(x,0,sizeof(x))
 7 #define clrmax(x) memset)x,0x3f3f3f3f,sizeof(x))
 8 using namespace std;
 9 const int N=1e5+10;
10 int ranked[N],order[N],backet[N],sa[N],key1[N],key2[N],height[N];
11 char s[N],vis[30];
12 int n,m,ans,k;
13 int unrep[N];
14 multiset<int> sum;
15 multiset<int>::iterator it;
16 bool cmp(int *r,int a,int b,int len)
17 {
18     return r[a]==r[b] && r[a+len]==r[b+len];
19 }
20 void da(int *sa,char *r,int n,int m)
21 {
22     int i,j,p,*x=key1,*y=key2,*t;
23     for(i=0;i<m;i++) backet[i]=0;
24     for(i=0;i<n;i++) backet[x[i]=r[i]]++;
25     for(i=1;i<m;i++) backet[i]+=backet[i-1];
26     for(i=n-1;i>=0;i--) sa[--backet[x[i]]]=i;
27     for(j=1,p=1;p<n;j*=2,m=p)
28     {
29         for(p=0,i=n-j;i<n;i++) y[p++]=i;
30         for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;
31         for(i=0;i<n;i++) order[i]=x[y[i]];
32         for(i=0;i<m;i++) backet[i]=0;
33         for(i=0;i<n;i++) backet[order[i]]++;
34         for(i=1;i<m;i++) backet[i]+=backet[i-1];
35         for(i=n-1;i>=0;i--) sa[--backet[order[i]]]=y[i];
36         for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++)
37             x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
38     }
39     return ;
40 }
41 void calheight(int *sa,char *r,int n)
42 {
43     int i,j,k=0;
44     for(i=1;i<=n;i++) ranked[sa[i]]=i;
45     for(i=0;i<n;i++)
46     {
47         if(k) k--;
48         j=sa[ranked[i]-1];
49         while(r[i+k]==r[j+k]) k++;
50         height[ranked[i]]=k;
51     }
52     return ;
53 }
54 int main()
55 {
56     int T;
57     scanf("%d",&T);
58     while(T--)
59     {
60         ans=0;
61         scanf("%d",&k);
62         scanf("%s",s);
63         n=strlen(s);
64         n++;
65         da(sa,s,n,200);
66         n--;
67         calheight(sa,s,n);
68         if(k==1)
69         {
70             height[1]=height[n+1]=0;
71             for(int i=1;i<=n;i++)
72              ans+=n-sa[i]-max(height[i],height[i+1]);
73             printf("%d\n",ans);
74             continue;
75          } 
76         sum.clear();
77         k--;
78         height[1]=0;
79         height[n+1]=0;
80         for(int i=2;i<=k;i++)
81             sum.insert(height[i]);
82         for(int i=k+1;i<=n;i++)
83         {
84             sum.insert(height[i]);
85             it=sum.begin();
86                 ans+=max(*it-max(height[i-k],height[i+1]),0);
87             sum.erase(sum.find(height[i-k+1]));
88         }
89         printf("%d\n",ans);
90     }
91     return 0;
92 }
View Code

 

 

posted @ 2017-09-11 21:56  hk_lin  阅读(970)  评论(0编辑  收藏  举报