2017 ACM-ICPC 亚洲区(沈阳赛区)网络赛 - 02 04 05 08 12

1004 array array array

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


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.
 

题意:
给你n个数,和k,问你去掉k个数之后,能不能形成不严格上升(下降)序列。

point:
直接正反求上升序列长l,l和n-k比较。

#include<iostream>
#include<string.h>
#include<stdio.h>
#include<math.h>
#include <algorithm>
#define LL long long
using namespace std;
const int maxn=1e5+3;

int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        int n,k;scanf("%d %d",&n,&k);
        int now[maxn];
        int a[maxn];
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        memset(now,0,sizeof now);
        int cnt=1;
        now[1]=a[1];
        for(int i=2; i<=n; i++)
        {
            if(a[i]>=now[cnt])
            {
                cnt++;
                now[cnt]=a[i];
            }
            else
            {
                int k=lower_bound(now,now+cnt,a[i])-now;
                now[k]=a[i];
            }
        }
        if(cnt>=n-k)
        {
            printf("A is a magic array.\n");
            continue;
        }
        cnt=1;
        now[1]=a[n];
        for(int i=n-1; i>=1; i--)
        {
            if(a[i]>=now[cnt])
            {
                cnt++;
                now[cnt]=a[i];
            }
            else
            {
                int k=lower_bound(now,now+cnt,a[i])-now;
                now[k]=a[i];
            }
        }
        if(cnt>=n-k)
        {
            printf("A is a magic array.\n");
            continue;
        }
        printf("A is not a magic array.\n");
        
    }
    return 0;
}


1002 cable cable cable

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


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.
 


题意:
看图,从每个k向下连线,让每k个组合m都能显示出k中颜色,即和每个k都连线。求最少的线。

POINT:
先让k1-m1,k2-m2,k3-m3……这样连下去。
然后后面的每个m都要连k条线,他们每个都必须和每个k相连。画一下就知道。
答案就是k+(m-k)*k。LL

#include<iostream>
#include<string.h>
#include<stdio.h>
#include<math.h>
#include <algorithm>
#define LL long long
using namespace std;
const int maxn=1e5+3;

int main()
{
    LL a,b;
    while(~scanf("%lld %lld",&a,&b))
    {
        printf("%lld\n",b+(a-b)*b);
    }
    return 0;
}


1005 number number number

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


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
 


题意:
给你一个斐波那契数列。给你一个k。在自然数中,有good和bad数,每一个good数都能用k个斐波那契加起来得到。bad数就是得不到的。
求最小的bad数。


POINT:
打表找规律。
1 :4
2 :12
3 :33
4 :88
5 :232
6 :609
7 :1596
8 :4180

发现答案就是第。5+2*(k-1) 个斐波那契数【-1】.
ans=F[5+2*(k-1)]-1。
k比较大,用矩阵快速幂求斐波那契数。


#include<iostream>
#include<string.h>
#include<stdio.h>
#include <map>
#include<math.h>
#define LL long long
using namespace std;
const LL maxn=1e5+3;
const LL mod = 998244353;
struct node
{
    LL a[3][3];
};
node chen(node a,node b)
{
    node ans;
    for(LL i=1;i<=2;i++)
    {
        for(LL j=1;j<=2;j++)
        {
            ans.a[i][j]=0;
            for(LL k=1;k<=2;k++)
            {
                (ans.a[i][j]+=a.a[i][k]*b.a[k][j])%=mod;
            }
        }
    }
    return ans;
}

node jzqkm(node base,LL mi)
{
    node ans;
    for(LL i=1;i<=2;i++)
    {
        for(LL j=1;j<=2;j++)
        {
            if(i==j) ans.a[i][j]=1;
            else ans.a[i][j]=0;
        }
    }
    while(mi)
    {
        if(mi&1) ans=chen(ans,base);
        mi>>=1;
        base=chen(base,base);
    }
    return ans;
}
int main()
{
    LL k;
    while(~scanf("%lld",&k))
    {
        node base;
        base.a[1][1]=1,base.a[1][2]=1,base.a[2][1]=1,base.a[2][2]=0;
        node ans=jzqkm(base,5+2*(k-1)-1);
        LL now=ans.a[1][1]*1;
        now=(now-1+mod)%mod;
        printf("%lld\n",now);
        
    }
    return 0;
}



1008 transaction transaction transaction

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


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
 


题意:
你可以选择任意两个城市买书或者卖书(可以同一个,收益=0)。
n-1条边链接n个城市,即一颗树。城市有距离,出发的花费为距离*1.求最大的话费。

POINT:
记忆化搜索,因为是无向边,所以不能计算好一个城市立马reutrn。
要记忆边,每条边分成两个方向。这样搜过一条边的话,那肯定不用搜下去了。
而不是靠点来reutrn。

#include<iostream>
#include<string.h>
#include<stdio.h>
#include <vector>
#include <math.h>
#include <algorithm>
#define LL long long
using namespace std;
const LL maxn=103030+3;
int cost[maxn];
struct edge
{
    int v,w;
};
int n;
vector<edge> len;
vector<int>G[maxn];
int vis[maxn];
int flag[maxn*2];
int dfs(int u,int pre)
{
    for(int i=0;i<G[u].size();i++)
    {
        int now=G[u][i];
        edge e = len[now];
        if(e.v==pre) continue;
        if(flag[now]) {
            vis[u]=max(vis[u],vis[e.v]+cost[e.v]-cost[u]-e.w);
            continue;
        }
        vis[u]=max(vis[u],dfs(e.v,u)+cost[e.v]-cost[u]-e.w);
        flag[now]=1;
    }
    return vis[u];
}
int sz;
void init()
{
    for(int i=1;i<=n;i++) G[i].clear(),vis[i]=0;
    memset(flag,0,sizeof flag);
    len.clear();
    sz=0;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        init();
        for(int i=1;i<=n;i++) scanf("%d",&cost[i]);
        for(int i=1;i<n;i++)
        {
            int u,v,w;scanf("%d %d %d",&u,&v,&w);
            edge e;
            e.v=v,e.w=w;
            len.push_back(e);
            G[u].push_back(sz++);
            e.v=u;
            len.push_back(e);
            G[v].push_back(sz++);
        }
        int ans=0;
        for(int i=1;i<=n;i++)
        {
            ans=max(ans,dfs(i,-1));
        }
        printf("%d\n",ans);
        
    }
    
    return 0;
}


1012 card card card

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


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
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.**
 

题意:
你可以对数列进行任意次操作,把最前面的已到最后面。
我们需要让拿的卡片最多,是第一列的数加起来最多。而不是手上拥有的,是历史拥有的。
求操作次数最少的且拿的卡片最多。

POINT:
思想为DP中的最大连续子序列和。记录len,当len==n时,则代表全部取掉了,直接break记录起点。
每次更新答案都记录起点。
赛中没看题目,结果会错意了。赛后立马A掉了,代码量也非常少。遗憾。


#include<iostream>
#include<stdio.h>
#include<string.h>
#define LL long long
using namespace std;
const int maxn = 1e6;
int n,a[maxn*2+10],b[maxn*2+10];

int main()
{
    while(~scanf("%d",&n))
    {
        for(int i=1;i<=n;i++) scanf("%d",&a[i]),a[i+n]=a[i];
        for(int i=1;i<=n;i++) scanf("%d",&b[i]),b[i+n]=b[i];
        int ans=0;
        int now=0;
        int get=0;
        int len=0;
        int k=-1;
        for(int i=1;i<=2*n;i++)
        {
            get+=a[i];
            len++;
            now+=a[i]-b[i];
            if(ans<get)
            {
                k=i-len+1;
            }
            if(len==n)
            {
                break;
            }
            if(now<0)
            {
                now=0;
                get=0;
                len=0;
                
            }
        }
        printf("%d\n",k-1);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值