zoukankan      html  css  js  c++  java
  • summer 2014 Round 4 解题报告

    Day 2:

      K-hash:

      这道题其实只要懂了后缀自动机就不难了。不过我还是做了很久。本来以为用个sort就可以让所有的节点按val从小到大排序,然后就能递推了。调试良久后发现排序后数组中每个元素的地址不会发生变化,只是值发生变化了,所以排序是没用的(因为p->o[i]和p->f都是指向的不变化的地址)。然后用priority_queue强行扭过了,速度还挺快,得瑟一下O(∩_∩)O~~

      (不知道zimpha怎么写的,跟开挂一样,又快内存又小,有机会的话找他请教一下。)

      这题其实直接按val值bfs一下就能得到按val值从小到大排序的点了...注意bfs的时候每次val值只能加1.

      

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstdlib>
     4 #include <cstring>
     5 #include <algorithm>
     6 #include <queue>
     7 #define FOR(i,l,r) for(int i=(l);i<=(r);i++)
     8 #define FORD(i,r,l) for(int i=(r);i>=(l);i--)
     9 #define rep(i,n) for(int i=0;i<(n);i++)
    10 #define res(i,s) for(int i=0;((s)[i]);i++)
    11 using namespace std;
    12 typedef long long LL;
    13 const int maxn=50001;
    14 
    15 char s[maxn];
    16 int k;
    17 
    18 struct sam{
    19     sam *o[10],*f;
    20     int val;
    21     LL v[32];
    22 }ssam[maxn*2],*bt,*last; int sct;
    23 sam *newd(int val)
    24 {
    25     sam *p=&ssam[sct++];
    26     rep(i,10) p->o[i]=0;
    27     p->f=0; p->val=val;
    28     rep(i,k) p->v[i]=0;
    29     return p;
    30 }
    31 void trans(char s)
    32 {
    33     int d=s-'0';
    34     sam *p=last,*np=newd(p->val+1); last=np;
    35     for (; p&&!p->o[d]; p=p->f) p->o[d]=np;
    36     if (!p) np->f=bt;
    37     else if (p->o[d]->val==p->val+1) np->f=p->o[d];
    38     else
    39     {
    40         sam *q=p->o[d],*nq=newd(p->val+1);
    41         memcpy(nq->o,q->o,sizeof(q->o));
    42         nq->f=q->f; q->f=np->f=nq;
    43         for (; p&&p->o[d]==q; p=p->f) p->o[d]=nq;
    44     }
    45 }
    46 void cl(sam *p)
    47 {
    48     for (int i=(p==bt?1:0); i<10; i++)
    49         if (p->o[i])
    50         {
    51             for (int j=0; j<k; j++)
    52                 p->o[i]->v[(j*10+i)%k]+=p->v[j];
    53         }
    54 }
    55 
    56 LL ans[32];
    57 void init() { sct=0; last=bt=newd(0); }
    58 void bl(sam *t,string s)
    59 {
    60     cout<<s<<endl;
    61     rep(i,10)
    62         if (t->o[i])
    63             bl(t->o[i],s+char('0'+i));
    64 }
    65 int main(){
    66     while (scanf("%s%d",s,&k)!=EOF)
    67     {
    68         init();
    69         res(i,s) trans(s[i]);
    70         //bl(bt,"");
    71         priority_queue<pair<int,int>, deque<pair<int,int> >, greater<pair<int,int> > > q;
    72         rep(z,sct) q.push(make_pair(ssam[z].val,z));
    73         bt->v[0]=1;
    74         while (!q.empty()) cl(&ssam[q.top().second]),q.pop();
    75         rep(i,k) ans[i]=0;
    76         FOR (i,1,sct-1) rep(j,k) ans[j]+=ssam[i].v[j];
    77         if (bt->o[0]) ans[0]++;
    78         rep(i,k) printf("%s%lld", i==0?"":" ", ans[i]);
    79         puts("");
    80     }
    81     return 0;
    82 }
    83 
    84 //greater是最小堆,priority_queue默认是最大堆
    View Code

    Day 4:

      Fixed Point

      题目总结:

      这种数论动规的关键点是在“与上届相等的数的处理”上,只要这个弄懂了,这种题应该就都会做了。

      因为和上届相等的数最多只有一个,所以我用一个equal来记录是否有满足条件的上届。而其他小于上届的数用f数组储存。

      策略只有取1和取0。

      小于上届的数可以随便取。

      equal的状态转移要好好想想:

      当前位为1:取1则equal保留,取0则equal可以转移到f数组。

      当前位为0:取0则equal保留。取1就比上届大了,舍去。

      一般性总结:

      1.打草稿分析样例很有效果。

      2.直接用不加证明的结论这种习惯不好。这道题中以及Coprime Sequence中已经深有体会。

     
     1 #include <iostream>
     2 #include <cstdlib>
     3 #include <cstdio>
     4 #include <cstring>
     5 #define FOR(i,l,r) for(int i=(l);i<=(r);i++)
     6 #define FORD(i,r,l) for(int i=(r);i>=(l);i--)
     7 #define rep(i,n) for(int i=0;i<(n);i++)
     8 using namespace std;
     9 typedef long long LL;
    10 typedef unsigned int ui;
    11 ui get2[33];
    12 
    13 LL f[33][33];
    14 LL gao(ui R, ui c, int k, int flag)
    15 {
    16     memset(f,0,sizeof(f));
    17     LL equal=1; int gs0=0;
    18     FORD (z,31,0)
    19     {
    20         //0
    21         if (flag>=0 || !(c&get2[z]))
    22         {
    23             FOR (i,1,32-z) f[z][i]=f[z+1][i-1];
    24             if (R&get2[z]) f[z][gs0+1]+=equal;
    25         }
    26         //1
    27         if (flag<=0 || (c&get2[z]))
    28         {
    29             FOR (i,0,31-z) f[z][i]+=f[z+1][i];
    30         }
    31         if ((R&get2[z]) && !(flag<=0 || (c&get2[z]))) equal=0;
    32         if (!(R&get2[z]) && !(flag>=0 || !(c&get2[z]))) equal=0;
    33         gs0+=!(R&get2[z]);
    34     }
    35     LL ret=0;
    36     FOR (i,0,32) if (abs(32-i-i)<=k) ret+=f[0][i];
    37     if (abs(32-gs0*2)<=k) ret+=equal;//~~
    38     return ret;
    39 }
    40 
    41 ui L,R,c; int k;
    42 LL gao0(int flag)
    43 {
    44     LL ret=gao(R,c,k,flag);
    45     if (L) ret-=gao(L-1u,c,k,flag);
    46     return ret;
    47 }
    48 
    49 int main()
    50 {
    51     get2[0]=1; for (int i=1;i<=32;i++) get2[i]=get2[i-1]<<1;
    52 
    53     int T; scanf("%d",&T);
    54     LL ans1,ans2,ans3;
    55     FOR (z,1,T)
    56     {
    57         scanf("%u%u%u%d",&L,&R,&c,&k);
    58         ans1=gao0(1);
    59         if (c!=0) ans2=0; else ans2=gao0(0);
    60         ans3=gao0(-1);
    61         printf("Case %d: %lld %lld %lld
    ",z,ans1,ans2,ans3);
    62     }
    63     return 0;
    64 }
    Fixed Point 代码
  • 相关阅读:
    alg--动态规划(dynamic planning)
    alg--分治法
    汇编-理解call,ret
    汇编--实验7
    leetCode笔记--binary tree
    leetCode笔记--(1)
    C#获取当前路径的方法如下
    VS2013 快捷键 与 RESHARPER 冲突
    使用Visual Studio 2013进行单元测试--初级篇
    VS 插件
  • 原文地址:https://www.cnblogs.com/monmonde/p/3910779.html
Copyright © 2011-2022 走看看