• 2014 ACM/ICPC Asia Regional Xi'an Online


    03 hdu5009

    状态转移方程很好想,dp[i] = min(dp[j]+o[j~i]^2,dp[i]) ,o[j~i]表示从j到i颜色的种数。

    普通的O(n*n)是会超时的,可以想到o[]最大为sqrt(n),问题是怎么快速找到从i开始往前2种颜色、三种、四种。。。o[]种的位置。

    离散化之后,可以边走边记录某个数最后一个出现的位置,初始为-1,而所要求的位置就等于

    if(last[a[i]]==-1) 该数没有出现过,num[i][1] = i,num[i][j+1] = num[i-1][j];

    else  last[a[i]]之前 num[i][1] = i,num[i][j+1] = num[i-1][j],之后num[i][j]= num[i-1][j];

     1 #include <iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<stdlib.h>
     6 #include<vector>
     7 #include<cmath>
     8 #include<queue>
     9 #include<set>
    10 #include<map>
    11 using namespace std;
    12 #define N 50010
    13 #define LL long long
    14 #define INF 0xfffffff
    15 const double eps = 1e-8;
    16 const double pi = acos(-1.0);
    17 const double inf = ~0u>>2;
    18 int a[N];
    19 int dp[N];
    20 int num[2][300],last[N];
    21 map<int,int>f;
    22 int main()
    23 {
    24     int i,j,n;
    25     while(scanf("%d",&n)!=EOF)
    26     {
    27         f.clear();
    28         int g =0 ;
    29         for(i = 1; i<= n ;i++)
    30         {
    31             scanf("%d",&a[i]);
    32             if(!f[a[i]])
    33             {
    34                 f[a[i]] = ++g;
    35                 a[i] = g;
    36             }
    37             else a[i] = f[a[i]];
    38         }
    39         for(i = 1; i <= n; i++)
    40         dp[i] = INF;
    41         memset(last,-1,sizeof(last));
    42         memset(num,0,sizeof(num));
    43         int k = sqrt(n*1.0)+1;
    44         int tk = 1;
    45         dp[1] = 1;
    46         last[a[1]] = 1;
    47         num[1][1] = 1;
    48         dp[0] = 0;
    49         for(i = 2; i <= n ;i++)
    50         {
    51             if(last[a[i]]==-1)
    52             {
    53                 tk+=1;
    54                 num[i%2][1] = i;
    55                 for(j = 1; j <= min(tk-1,k-1) ; j++)
    56                 num[i%2][j+1] = num[(i-1)%2][j];
    57             }
    58             else
    59             {
    60 
    61                 num[i%2][1] = i;
    62                 for(j = 1; j < min(k,tk) ; j++)
    63                 {
    64                     if(last[a[i]]==num[(i-1)%2][j]) break;
    65                     num[i%2][j+1] = num[(i-1)%2][j];
    66                 }
    67                 for(int g = j+1 ; g <= min(tk,k) ; g++)
    68                 num[i%2][g] = num[(i-1)%2][g];
    69             }
    70             last[a[i]] = i;
    71             for(j = 1; j <= min(k,tk); j++)
    72             {
    73                 int po = num[i%2][j+1];
    74                 dp[i] = min(dp[i],dp[po]+j*j);
    75                // cout<<dp[po]<<" "<<po<<endl;
    76             }
    77         }
    78         printf("%d
    ",dp[n]);
    79 
    80     }
    81     return 0;
    82 }
    View Code

    09 hdu5015

    构造矩阵

    先构造出1*(n+2)的矩阵 (233, 233+a1, 233+a1+a2, 233+a1+a2+a3, ..., 233+a1+a2+..+an, 1),表示第一列上的值。

    此矩阵为A,然后想要使A*B = C,C为第二列的值,所以B可以为

    10 10 10 10 10 .......0

    0   1    1   1   1........0

    0   0    1   1   1........0

    0   0    0   1   1........0

    0   0    0   0   1........0

    3   3    3   3   3........1

    然后快速幂就可以了。。

      1 #include <iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<stdlib.h>
      6 #include<vector>
      7 #include<cmath>
      8 #include<queue>
      9 #include<set>
     10 using namespace std;
     11 #define N 12
     12 #define LL __int64
     13 #define INF 0xfffffff
     14 const double eps = 1e-8;
     15 const double pi = acos(-1.0);
     16 const double inf = ~0u>>2;
     17 #define mod 10000007
     18 struct Mat
     19 {
     20     LL mat[N][N];
     21 };
     22 int n;
     23 int a[N];
     24 Mat operator * (Mat a,Mat b)
     25 {
     26     Mat c;
     27     memset(c.mat,0,sizeof(c.mat));
     28     int i,j,k;
     29     for(k =0 ; k < n ; k++)
     30     {
     31         for(i = 0 ; i < n ; i++)
     32         {
     33             if(a.mat[i][k]==0) continue;//优化
     34             for(j = 0 ; j < n ; j++)
     35             {
     36                 if(b.mat[k][j]==0) continue;//优化
     37                 c.mat[i][j] = (c.mat[i][j]+(a.mat[i][k]*b.mat[k][j])%mod)%mod;
     38             }
     39         }
     40     }
     41     return c;
     42 }
     43 Mat operator ^(Mat a,int k)
     44 {
     45     Mat c;
     46     int i,j;
     47     for(i =0 ; i < n ; i++)
     48         for(j = 0; j < n ; j++)
     49             c.mat[i][j] = (i==j);
     50     for(; k ; k >>= 1)
     51     {
     52         if(k&1) c = c*a;
     53         a = a*a;
     54     }
     55     return c;
     56 }
     57 int main()
     58 {
     59     int m,i,j;
     60     Mat c;
     61     while(scanf("%d%d",&n,&m)!=EOF)
     62     {
     63         memset(c.mat,0,sizeof(c.mat));
     64         for(i = 0 ; i <= n; i++)
     65         {
     66             c.mat[0][i] = 10;
     67             for(j = 1 ; j <= i ; j++)
     68                 c.mat[j][i] = 1;
     69         }
     70         for(i = 0 ; i <= n ; i++)
     71             c.mat[n+1][i] = 3;
     72         c.mat[n+1][n+1] = 1;
     73         LL s = 233;
     74         Mat ans;
     75         memset(ans.mat,0,sizeof(ans));
     76         ans.mat[0][0] = s;
     77         for(i = 1; i <= n; i++)
     78         {
     79             scanf("%d",&a[i]);
     80             s+=a[i];
     81             s%=mod;
     82             ans.mat[0][i] = s;
     83         }
     84         ans.mat[0][n+1] = 1;
     85         int tn = n;
     86         n+=2;
     87         if(m>1)
     88         ans = ans*(c^(m-1));
     89 //        for(i = 0 ; i < n ; i++)
     90 //            {for(j = 0; j< n ; j++)
     91 //        cout<<c.mat[i][j]<<" ";
     92 //        puts("");
     93 //            }
     94 //        for(i = 0 ; i < n ; i++)
     95 //        {
     96 //            for(j = 0; j < n ; j++)
     97 //                cout<<ans.mat[i][j]<<" ";
     98 //            puts("");
     99 //        }
    100         printf("%I64d
    ",ans.mat[0][tn]);
    101     }
    102     return 0;
    View Code
  • 相关阅读:
    挺好的程序员面试网址
    [转]浅谈协方差矩阵
    坚持
    matlab中文论坛
    看书
    Opengl绘制点
    说服力
    心情
    vector操作
    我的毕设
  • 原文地址:https://www.cnblogs.com/shangyu/p/3971984.html
Copyright © 2020-2023  润新知