成都网赛

第一题:http://acm.hdu.edu.cn/showproblem.php?pid=2428

             和北大此题几乎一模一样

            http://acm.pku.cn/JudgeOnline/problem?id=2002

第三题:

http://acm.hdu.edu.cn/showproblem.php?pid=2430

记录某个余数最开始出现的位置,然后再在线性时间里计算最多数。网赛时已经想到了这种思路,并且写了代码的雏形。但是因为自己代码错误性高,没有得到很多写的时间以及检查,很可惜,原来是一处数组用错了导致wa了。

#include <iostream>
using namespace std;
#define N 1000001
int a[N],pp[N],lef[N],arr[N],b[N],p,k;
void bsearch(int low, int high,int v)
{
    int tt=(high+1)%p;
    int y,l=0,x=low;
    while(arr[x]!=-1){
        y=b[x];
   if(y-x>0)
    l+=y-x;
   else
    l+=y-x+p;
        if(l>k)
    return;
   b[x]=tt;
   x=y;
     }   
     while(arr[x]==-1){
            arr[x]=v;
            b[x]=tt;
    l++;
            if(l>k)
              return;
            x=(x+1)%p;
    }  
}
int main()
{
    int t,n,tt,res,kk,i;
    scanf("%d",&t);
    for(kk=1;kk<=t;kk++)
    {
        scanf("%d%d%d",&n,&p,&k);
        memset(arr,-1,sizeof(arr));
        for(i=1;i<=n;i++)
          scanf("%d",&a[i]);
        pp[0]=0;
        lef[0]=0;
        tt=(k+1)%p;
        for(i=0;i<=k;i++){
          arr[i]=0;
          b[i]=tt;
        }
        res=-1;
        for(;i<p-1;i++)
          b[i]=i+1;
        b[p-1]=0;
        for(i=1;i<=n;i++)
        {
            lef[i]=lef[i-1]+a[i];
            pp[i]=pp[i-1]+lef[i]/p;
            lef[i]%=p;
            if(arr[lef[i]]!=-1){
                tt=pp[i]-pp[arr[lef[i]]];
                if(lef[arr[lef[i]]]>lef[i])
                  tt--;
                if(tt>res)
                  res=tt;
            }  
            bsearch(lef[i],(lef[i]+k)%p,i);
        }
        printf("Case %d: %d\n",kk,res);
    }   
    return 0;
}  

转解题报告:

1001: 枚举正方形对角线上的两个点(x1, y1), (x3, y3),然后通过计算可得:
正方形上的另外两个点是(x1, y3), (x3, y1), 当然,对角线上的两个点需要满足正方形的特点,这里需要特判一下。

1002: 以单词为点,能前后相连的单词之间连边,得到一个有向图,求长度为奇数且小于等于N的不同的S->T的路径数。设邻接矩阵为A,则可通过求A
+ A ^ 3 + ... + A ^ N求解。构造一个矩阵后可通过logN次矩阵乘求解。

1003:
Define S[i] as the sum of the first i elements of the given number sequence A.
Define R[i] as the reminder of Si module P: R[i] = S[i] % P.
Then the target of this problem is to find a maximum partial summation
of A which satisfy the reminder of it module P isn't bigger than K.
That is:
max{s[i] - s[j]} st. j < i && (s[i] - s[j]) % p <= K
The number given are all non-negative, so max{s[i] – s[j]} is equal to
min{j}. With the help of the sorted R sequence, we can obtain a linear
solution to this problem.

1004:
The problem is equivalent to the following problem:
How many ways to divide an positive integer N to integers larger than
1? ( We consider integers with the same value to be the same.)
Such problem can be solved easily by simple dynamic programming in O(N^2) time.

1005:
注意到K<N,可以推导所求的第K项分子不会大于3,枚举一下分子然后二分分母再求出之前的项数,这样时间复杂度是O(logN),或者直接找规律,时间复杂度O(1)

1006:
暴力算法:枚举每条边,然后对每个点求一次单源最短路,由于题目中的边的权值都是1,因此可以用bfs来求得每个点的单源最短路。复杂度是O(M*N*M)。由于M*N*M=3000*100*3000=9*10^8,
因此只能通过数据规模较小的测试数据。
标程算法:仍然使用上面的思路,但要作一些预处理。对每个顶点u求一次单源最短路,把求得的结果称作u的最短路径树。若被破坏的公路不在该最短路径树上,则从u出发的所有最短路径的总和就是u到该树上的所有顶点的路径的总和,这里可以作O(M)的预处理,然后花费O(1)时间就能返回结果;否则,删除被破坏的公路后,从新计算从u出发的所有最短路径的总和,这步的复杂度是O(M)。由于最短路径树上只有N-1条边,因此需要从新计算的次数只有N-1次。因此,程序的复杂度变为O(N*N*M)=3*10^7。

1007: 模拟题。按照规则模拟,注意" The top card of the remaining stock is exposed to
start the game, treated as if player 1 dropped that card" 和 "If the
last card is an action card, the special effect still occurs." 即可。

1008: 网络流。设原来的源和汇分别为s和t,先用一次最大流算法求出残余网络,设对应的最小割集为(S,T)。那么分别求以s为源点,|S|中的其它点为汇点的最大流的最大值,以及以|T|中的其它点为源点,t为汇点的最大流的最大值。两个最大值的较小值即为答案。

1009:
比较简单的做法是"移动"球心直到其在x,y,z轴上都接触到长方体为止(例如对于X轴,也就是计算满足MinX<=BallX'<=MaxX的最小的|BallX'-BallX|,
MinX和MaxX是长方体X轴的最小最大坐标,BallX和BallX'是移动前后球心X坐标),判断移动的距离是否少于半径即可。

1010:
Notice that the graph given is acyclic, so we can use dynamic
programming to calculate the optimal solution in topological order.
O(MK)

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值