zoukankan      html  css  js  c++  java
  • 2014 ACM/ICPC Asia Regional Xi'an Online

    Post Robot http://acm.hdu.edu.cn/showproblem.php?pid=5007

    字符串比较

     1 #include<cstdio>
     2 char a[110];
     3 char A[]="MAI MAI MAI!";
     4 char B[]="SONY DAFA IS GOOD!";
     5 char apple[4][8]={"Apple","iPhone","iPod","iPad"};
     6 char sony[]="Sony";
     7 bool judge(char my[],int s){
     8     for(int i=0;my[i];i++){
     9         if(my[i]!=a[s+i]) return false;
    10     }
    11     return true;
    12 }
    13 int main(){
    14     while(gets(a)){
    15         for(int i=0;a[i];i++){
    16             if(judge(sony,i)){
    17                 puts(B);
    18                 continue;
    19             }
    20             for(int j=0;j<4;j++){
    21                 if(judge(apple[j],i)){
    22                     puts(A);
    23                     break;
    24                 }
    25             }
    26         }
    27     }
    28     return 0;
    29 }
    View Code

    Boring String Problem http://acm.hdu.edu.cn/showproblem.php?pid=5008

    先后缀数组,然后遍历处理出前几个后缀能构成的不同字串,存sum中。然后找第k个的时候二分sum,就知道第k个在第几个后缀中。然后能构成这个串的不一定只有一个,只要字典序大的那些前缀够长,也不是没有可能嘛。所以要往下找一个区间,区间内的height要大于等于这个串的长度,height是公共前缀长度。然后对这个区间求最小的sa。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<cmath>
      4 #include<algorithm>
      5 using namespace std;
      6 typedef __int64 LL;
      7 const int M=100010;
      8 class Range_Maximum_Query{///区间最值查询离线算法init_o(nlogn),query_o(1)
      9     int LOG[M],dpmax[M][20],dpmin[M][20];
     10 public:
     11     void init(){///使用类前调用一次即可
     12         LOG[0]=-1;
     13         for(int i=1;i<M;i++){
     14             LOG[i]=LOG[i>>1]+1;
     15         }
     16     }
     17     void Make_RMQ(int n,int a[]){///传入点的个数,下标1开始
     18         for(int i=1;i<=n;i++){
     19             dpmax[i][0]=dpmin[i][0]=a[i];
     20         }
     21         for(int j=1;j<=LOG[n];j++){
     22             for(int i=1;i+(1<<j)-1<=n;i++){
     23                 dpmax[i][j]=max(dpmax[i][j-1],dpmax[i+(1<<(j-1))][j-1]);
     24                 dpmin[i][j]=min(dpmin[i][j-1],dpmin[i+(1<<(j-1))][j-1]);
     25             }
     26         }
     27     }
     28     int get_RMQ(int a,int b,bool big){///传入1返回max,传入0返回min
     29         int k=LOG[b-a+1];
     30         if(big)
     31         return max(dpmax[a][k],dpmax[b-(1<<k)+1][k]);
     32         return min(dpmin[a][k],dpmin[b-(1<<k)+1][k]);
     33     }
     34 }rmqsa,rmqheight;
     35 class Suffix_Array {  ///后缀数组
     36     static const int MV=M;///串长度
     37 public:
     38     int n,m,i,j,k,p,str[MV],sa[MV],height[MV],Rank[MV],wa[MV],wb[MV],wv[MV],ws[MV];///sa按字典序排序后后缀下标,rank后缀的排名,height排名相邻两个后缀的最长公共前缀
     39     bool cmp(int r[],int a,int b,int len) {
     40         return r[a]==r[b]&&r[a+len]==r[b+len];
     41     }
     42     void buildsa() {
     43         int *x=wa,*y=wb;
     44         for(i=0; i<m; i++) ws[i]=0;
     45         for(i=0; i<n; i++) ws[x[i]=str[i]]++;
     46         for(i=1; i<m; i++) ws[i]+=ws[i-1];
     47         for(i=n-1; i>=0; i--) sa[--ws[x[i]]]=i;
     48         for(j=p=1; p<n; j<<=1,m=p) {
     49             for(p=0,i=n-j; i<n; i++) y[p++]=i;
     50             for(i=0; i<n; i++) if(sa[i]>=j) y[p++]=sa[i]-j;
     51             for(i=0; i<m; i++) ws[i]=0;
     52             for(i=0; i<n; i++) ws[wv[i]=x[y[i]]]++;
     53             for(i=1; i<m; i++) ws[i]+=ws[i-1];
     54             for(i=n-1; i>=0; i--) sa[--ws[wv[i]]]=y[i];
     55             for(swap(x,y),x[sa[0]]=0,p=i=1; i<n; i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
     56         }
     57     }
     58     void buildheight() {
     59         for(i=1; i<=n-1; i++) Rank[sa[i]]=i;
     60         for(i=k=0; i<n-1; height[Rank[i++]]=k)
     61             for(k?k--:0,j=sa[Rank[i]-1]; str[i+k]==str[j+k]; k++);
     62     }
     63     int getsa(int id) {
     64         return sa[id];
     65     }
     66     int getheight(int id) {
     67         return height[id];
     68     }
     69     int getrank(int id) {
     70         return Rank[id];
     71     }
     72     void build(char s[],int len,int cl) {///n为字符串长度加一,m为最大字符值加一
     73         n=len;
     74         m=cl;
     75         for(int i=0; i<=len; i++) str[i]=s[i];
     76         str[len]=0;
     77         buildsa();
     78         buildheight();
     79     }
     80 } gx;
     81 char a[M];
     82 LL sum[M];
     83 int main(){
     84     rmqsa.init();
     85     rmqheight.init();
     86     while(~scanf("%s",a)){
     87         int n=strlen(a);
     88         gx.build(a,n+1,256);
     89         rmqsa.Make_RMQ(n,gx.sa);
     90         rmqheight.Make_RMQ(n,gx.height);
     91         LL tmp;
     92         sum[0]=0;
     93         for(int i=1;i<=n;i++){
     94             tmp=n-gx.getsa(i)-gx.getheight(i);
     95             sum[i]=sum[i-1]+tmp;
     96         }
     97         int q;
     98         LL v,l=0,r=0;
     99         scanf("%d",&q);
    100         while(q--){
    101             scanf("%I64d",&v);
    102             LL k=(l^r^v)+1;
    103             if(k>sum[n]){
    104                 l=r=0;
    105                 puts("0 0");
    106                 continue;
    107             }
    108             int id=lower_bound(sum,sum+n,k)-sum;
    109             l=gx.getsa(id);
    110             r=n-1;
    111             LL cha=sum[id]-k;
    112             r-=cha;
    113             int len=r-l+1;
    114             int L=id+1,R=n;
    115             int to=id;
    116             while(L<=R){
    117                 int mid=(L+R)>>1;
    118                 if(rmqheight.get_RMQ(id+1,mid,0)>=len){
    119                     to=max(to,mid);
    120                     L=mid+1;
    121                 }
    122                 else{
    123                     R=mid-1;
    124                 }
    125             }
    126             l=rmqsa.get_RMQ(id,to,0);
    127             r=l+len-1;
    128             l++;
    129             r++;
    130             printf("%I64d %I64d
    ",l,r);
    131         }
    132     }
    133     return 0;
    134 }
    View Code

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

    用的是尼姆博弈的结论,至于为什么和原来的尼姆博弈的结论是一样一样的,好像可以证明。

    尼姆博弈的结论是,全部异或起来为零先手输,否则先手赢。说明先手总能通过拿一定量的石头,使得剩下的异或值为零,然后零状态给后手,后手就输了,所以异或不为零,先手能赢。如果全部异或为零,由于先手必须拿至少一个,也就是说剩下的肯定比原来的小一些,那么异或起来肯定不能为零,也就是先手拿完一定会把非零的情况给后手,先手输。

    现在多了一种拿法,就是拿完可以分两堆。

    分类讨论,如果先手拿了非零的情况,那按照尼姆博弈的拿法,一定能变成零状态给后手,先手赢。

    如果先手拿零的情况,拿完以后,剩下的如果不分,就和原来的尼姆博弈一样,一定会输,如果分两块,由于这两块之和小于原来的个数,所以他们异或一定小于原来的个数,所以一定会异或出非零的情况给后手,那么先手输了。

     1 #include<cstdio>
     2 int main(){
     3     int n,a;
     4     while(~scanf("%d",&n)){
     5         int ans=0;
     6         while(n--){
     7             scanf("%d",&a);
     8             ans^=a;
     9         }
    10         puts(ans?"Win":"Lose");
    11     }
    12     return 0;
    13 }
    View Code

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

    bfs 4个方向转,把转的置换写出来会比较好。用string表示状态,用map来判重,会方便很多,但是c++会ce,用g++交就ac,也是有点坑。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<queue>
     4 #include<map>
     5 using namespace std;
     6 string S,E;
     7 map<string,bool> vis;
     8 struct Q{
     9     int step;
    10     string sta;
    11 }now,pre;
    12 queue<Q> q;
    13 int zhuan[4][8]={
    14     {2,3,1,0,4,5},
    15     {3,2,0,1,4,5},
    16     {4,5,2,3,1,0},
    17     {5,4,2,3,0,1},
    18 };
    19 int bfs(){
    20     vis.clear();
    21     vis[S]=true;
    22     now.sta=S;
    23     now.step=0;
    24     while(!q.empty()) q.pop();
    25     q.push(now);
    26     while(!q.empty()){
    27         pre=q.front();
    28         q.pop();
    29         if(pre.sta==E) return pre.step;
    30         for(int i=0;i<4;i++){
    31             for(int j=0;j<6;j++){
    32                 now.sta[j]=pre.sta[zhuan[i][j]];
    33             }
    34             now.sta.resize(6);
    35             if(!vis[now.sta]){
    36                 vis[now.sta]=true;
    37                 now.step=pre.step+1;
    38                 q.push(now);
    39             }
    40         }
    41     }
    42     return -1;
    43 }
    44 int main(){
    45     char op[2];
    46     while(~scanf("%s",op)){
    47         S=op[0];
    48         for(int i=1;i<6;i++){
    49             scanf("%s",op);
    50             S+=op[0];
    51         }
    52         E="";
    53         for(int i=0;i<6;i++){
    54             scanf("%s",op);
    55             E+=op[0];
    56         }
    57         printf("%d
    ",bfs());
    58     }
    59     return 0;
    60 }
    View Code

    Number Sequence http://acm.hdu.edu.cn/showproblem.php?pid=5014

    还是贪心的构造,这是参考清华大学team0790 的,每次都构造取反的数,每次都能生成全1的数。这样和最大。

     1 #include<cstdio>
     2 typedef __int64 LL;
     3 const int M=100010;
     4 LL sum;
     5 int ans[M];
     6 void construct(int n) {
     7     sum=0;
     8     for(int i=19; i>=0&&n>=0; i--)
     9         if(n&(1<<i)) {
    10             int s=(2<<i)-1;///s是位数和n一样的全1的数
    11             for(int j=s-n; j<=n; j++) {///从n按位取反到n一一赋值,每次都恰好构造出全1.
    12                 ans[j]=s-j;
    13                 sum+=s;
    14             }
    15             n=s-n-1;
    16         }
    17     if(!n)
    18         ans[0]=0;
    19 }
    20 int main() {
    21     int n,a;
    22     while(~scanf("%d",&n)) {
    23         construct(n);
    24         printf("%I64d
    ",sum);
    25         for(int i=0; i<=n; i++) {
    26             scanf("%d",&a);
    27             printf("%d ",ans[a]);
    28         }
    29         puts("");
    30     }
    31     return 0;
    32 }
    View Code

    根据他们的算法,每个数都能匹配,并且正好能是个排列,所以就直接取反了。

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 typedef __int64 LL;
     5 const int M=100010;
     6 int a[M],b[M],two[32];
     7 int main(){
     8     int n;
     9     two[0]=1;
    10     for(int i=1;i<=20;i++){
    11         two[i]=two[i-1]*2;
    12     }
    13     while(~scanf("%d",&n)){
    14         for(int i=0;i<=n;i++){
    15             scanf("%d",&a[i]);
    16             b[i]=-1;
    17         }
    18         for(int i=n;i>=0;i--){
    19             if(b[i]!=-1) continue;
    20             int ci=upper_bound(two,two+20,i)-two;
    21             int fan=two[ci]-1-i;
    22             b[fan]=i;
    23             b[i]=fan;
    24         }
    25         LL ans=0;
    26         for(int i=0;i<=n;i++){
    27             ans+=i^b[i];
    28         }
    29         printf("%I64d
    ",ans);
    30         for(int i=0;i<=n;i++){
    31             if(i) printf(" ");
    32             printf("%d",b[a[i]]);
    33         }
    34         puts("");
    35     }
    36     return 0;
    37 }
    View Code

    233 Matrix http://acm.hdu.edu.cn/showproblem.php?pid=5015

    观察可以发现,是序列是递推的,递推10的9次方,所以矩阵快速幂了一下,关键是推出递推矩阵,每一项的都是前几项之和,第一项是233*10+3

     1 #include<cstdio>
     2 #include<cstring>
     3 #define mt(a,b) memset(a,b,sizeof(a))
     4 typedef __int64 LL;
     5 const int mod=10000007;///%mod
     6 class Matrix { ///矩阵 下标0开始
     7     typedef LL typev;///权值类型
     8     static const int MV=16;///矩阵长度
     9     static const int mod=10000007;///%mod
    10     friend Matrix operator *(const Matrix &a,const Matrix &b) { ///矩阵乘法,必须a的列等于b的行
    11         Matrix ret;
    12         ret.n=a.n;
    13         ret.m=b.m;
    14         ret.zero();
    15         if(a.m==b.n) {
    16             for(int k=0; k<a.m; k++) {
    17                 for(int i=0; i<a.n; i++) {
    18                     if(a.val[i][k]) {
    19                         for(int j=0; j<b.m; j++) {
    20                             ret.val[i][j]+=a.val[i][k]*b.val[k][j];
    21                             ret.val[i][j]%=mod;///看具体需要
    22                         }
    23                     }
    24                 }
    25             }
    26         }
    27         return ret;
    28     }
    29     friend Matrix operator ^ (Matrix &a,int b) {///必须是n*n方阵才能快速幂
    30         Matrix ret;
    31         ret.n=ret.m=a.n;
    32         ret.unit();
    33         for(; b; a=a*a,b>>=1) {
    34             if(b&1) {
    35                 ret=ret*a;
    36             }
    37         }
    38         return ret;
    39     }
    40 public:
    41     int n,m;///n行m列
    42     typev val[MV][MV];
    43     void zero() {
    44         mt(val,0);
    45     }
    46     void unit() {
    47         zero();
    48         for(int i=0; i<MV; i++)
    49             val[i][i]=1;
    50     }
    51 } A;
    52 LL a[16];
    53 int main(){
    54     int n,m;
    55     while(~scanf("%d%d",&n,&m)){
    56         a[0]=3;
    57         a[1]=233;
    58         for(int i=2;i<=n+1;i++){
    59             scanf("%I64d",&a[i]);
    60         }
    61         A.zero();
    62         A.val[0][0]=1;
    63         A.val[1][0]=1;
    64         A.val[1][1]=10;
    65         for(int i=2;i<=n+1;i++){
    66             for(int j=1;j<=i;j++){
    67                 A.val[i][j]=1;
    68             }
    69         }
    70         A.n=A.m=n+2;
    71         A=A^m;
    72         LL ans=0;
    73         for(int j=0;j<n+2;j++){
    74             ans+=A.val[n+1][j]*a[j];
    75             ans%=mod;
    76         }
    77         printf("%I64d
    ",ans);
    78     }
    79     return 0;
    80 }
    View Code

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

    康神写的模拟退火,我不会,待补。

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<string>
      6 #include<queue>
      7 #include<map>
      8 #include<cmath>
      9 #include<stack>
     10 #include<algorithm>
     11 #include<functional>
     12 #include<stdarg.h>
     13 using namespace std;
     14 #ifdef __int64
     15 typedef __int64 LL;
     16 #else
     17 typedef long long LL;
     18 #endif
     19 
     20 double esp = 10e-6;
     21 
     22 typedef struct Point {
     23     double a,b,c;
     24     double l;
     25     inline double dis (const Point&p)const {
     26         return (p.a-a)*(p.a-a) + (p.b-b)*(p.b-b) +(p.c-c)*(p.c-c);
     27     }
     28     inline double dis()const {
     29         return l;
     30     }
     31     void init(double a,double b,double c) {
     32         this->a=a;
     33         this->b=b;
     34         this->c=c;
     35         l = a*a + b*b + c*c;
     36     }
     37     inline bool less(const Point&p)const {
     38         return l < p.l;
     39     }
     40 } Point;
     41 
     42 typedef struct {
     43     double a,b,c,d,e,f;
     44     Point ans;
     45     double r;
     46     vector<Point> testPoint;
     47     bool read() {
     48         return ~scanf("%lf%lf%lf%lf%lf%lf",&a,&b,&c,&d,&e,&f);
     49     }
     50     //随意找到一个局部最优的
     51     void getFirstAns() {
     52         r = max(a,b);
     53         r = max(r,c);
     54         ans.init(0,0,sqrt(1/r));
     55     }
     56 
     57     //得到一个范围半径
     58     void initRadius() {
     59         r = min(a,b);
     60         r = min(r,c);
     61         r = 1/r;
     62     }
     63 
     64     //模拟退火得到答案
     65     void solve() {
     66 
     67         int size;
     68         bool ok = false;
     69         while(r>esp) {
     70             ok = false;
     71             testPoint.clear();
     72             getTestPoint();
     73             size = testPoint.size();
     74             for(int i=0; i<size; i++) {
     75                 if(testPoint[i].less(ans)) {
     76                     ans = testPoint[i];
     77                     ok = true;
     78                 }
     79             }
     80             if(ok == false) {
     81                 r = r/2;
     82             }
     83 
     84         }
     85     }
     86 
     87 
     88     void getZ(double x, double y) {
     89         double z;
     90         double a0,b0,c0;
     91         a0 = c;
     92         b0 = d*y + e*x;
     93         c0 = a*x*x + b*y*y + f*x*y - 1;
     94         double d0 = b0*b0 - 4*a0*c0;
     95         Point point;
     96         if(d0 >= 0) {
     97             d0 = sqrt(d0);
     98             z = (-b0+d0)/(2*a0);
     99             point.init(x,y,z);
    100             testPoint.push_back(point);
    101             z = (-b0-d0)/(2*a0);
    102             point.init(x,y,z);
    103             testPoint.push_back(point);
    104         }
    105     }
    106     void getY(double x,double z) {
    107         double y;
    108         double a0,b0,c0;
    109         a0 = b;
    110         b0 = d*z+f*x;
    111         c0 = a*x*x+c*z*z+e*x*z-1;
    112         double d0 = b0*b0 - 4*a0*c0;
    113         Point point;
    114         if(d0 >= 0) {
    115             d0 = sqrt(d0);
    116             y = (-b0+d0)/(2*a0);
    117             point.init(x,y,z);
    118             testPoint.push_back(point);
    119             y = (-b0-d0)/(2*a0);
    120             point.init(x,y,z);
    121             testPoint.push_back(point);
    122         }
    123     }
    124     void getX(double y,double z) {
    125         double x;
    126         double a0,b0,c0;
    127         a0 = a;
    128         b0 = e*z+f*y;
    129         c0 = b*y*y+c*z*z+d*y*z-1;
    130         double d0 = b0*b0 - 4*a0*c0;
    131         Point point;
    132         if(d0 >= 0) {
    133             d0 = sqrt(d0);
    134             x = (-b0+d0)/(2*a0);
    135             point.init(x,y,z);
    136             testPoint.push_back(point);
    137             x = (-b0-d0)/(2*a0);
    138             point.init(x,y,z);
    139             testPoint.push_back(point);
    140         }
    141     }
    142 
    143     //找目前最优解周围的若干点
    144     //为了简单,采用以目前最优解为中心的立方体的26*2个点作为周围点
    145     //任意确定两个点的坐标,可以用方程求出第三个点的坐标。
    146     void getTestPoint() {
    147         double x,y,z;
    148         x = ans.a;
    149         y = ans.b;
    150         z = ans.c;
    151         for(int i=-1; i<=1; i++) {
    152             for(int j=-1; j<=1; j++) {
    153                 getZ(x+r*i,y+r*j);
    154                 getX(y+r*i,z+r*j);
    155                 getY(x+r*i,z+r*j);
    156             }
    157 
    158         }
    159     }
    160 
    161     double getAns() {
    162         return sqrt(ans.l);
    163     }
    164 
    165 } Ellipsoid;
    166 
    167 int main() {
    168 
    169     Ellipsoid ellipsoid;
    170     while(ellipsoid.read()) {
    171         ellipsoid.getFirstAns();
    172         ellipsoid.initRadius();
    173         ellipsoid.solve();
    174         printf("%.8f
    ",ellipsoid.getAns());
    175     }
    176 
    177     return 0;
    178 }
    View Code

    end

  • 相关阅读:
    正则 不匹配某个单词
    希赛 系统架构设计师教程 勘误
    QQ 快速登录中获取用户信息
    requests 配置tor代理后提示'Failed to establish a new connection: [Errno -2] Name or service not known'
    xadmin choice filter 多选
    kali linux 热点 无法获取IP
    windows10 输入法添加小鹤双拼
    del: recycle for linux
    安装WSL2
    cmake(转载)
  • 原文地址:https://www.cnblogs.com/gaolzzxin/p/3971423.html
Copyright © 2011-2022 走看看