zoukankan      html  css  js  c++  java
  • 【2012天津区域赛】部分题解 hdu4431—4441

    1001:

    题意:
    给你13张麻将牌,问可以胡哪些张

    思路:

    枚举可能接到的牌,然后dfs判断能否胡

    1002:

    题意:

    已知n,m 求 n的所有约数在m进制下的平方和

    做法:
    队长用java高精度写的

    代码:

    import java.io.BufferedInputStream;
    import java.io.BufferedOutputStream;
    import java.io.PrintWriter;
    import java.io.ObjectInputStream.GetField;
    import java.math.BigDecimal;
    import java.math.BigInteger;
    import java.util.Scanner;
    
    public class Main {
        
        static BigInteger getSum(int i, int base){
            BigInteger ans= BigInteger.ZERO;
            BigInteger divider = BigInteger.valueOf(i);
            String s = divider.toString(base);
    
            for (int j = 0; j < s.length(); j++) {
                BigInteger k = new BigInteger(s.substring(j, j + 1),
                        base);
                ans = k.multiply(k).add(ans);
            }
            return ans;
        }
        
        public static void main(String[] args) {
            Scanner cin = new Scanner(new BufferedInputStream(System.in));
            PrintWriter cout = new PrintWriter(new BufferedOutputStream(System.out));
    
            while (cin.hasNext()) {
                int n = cin.nextInt();
                int base = cin.nextInt();
    
                BigInteger ans = BigInteger.ZERO;
                for (int i = 1; i * i <= n; i++){
                    if (n % i == 0) {
                        // i是divider
                        ans = ans.add(getSum(i, base));
                        if(i*i!=n)
                            ans = ans.add(getSum(n/i, base));
                    }
                    
                }
                cout.println(ans.toString(base).toUpperCase());
            }
                
            
    
            cin.close();
            cout.close();
        }
    
    }
    View Code

    1003:

    题意:
    给定一串数,每次有三种操作:

    1.把当前数加/减1

    2.当前数和后面一个数加/减1

    3.当前数和后面两个数加/减1

    (加减完后的结果是在0~9循环的)

    求把当前状态变到目标状态需要的最小操作数

    做法:

    处理到每个数的时候最多对后面两个数产生影响,因此十进制最多有 10^2=100 种情况,可以全部存下
    可以进行dp,dp[i][j]表示前i个数已经达到目标状态 ,第i+1个数和第i+2个数的被操作情况为j(状压一下)的最小操作数,转移只需要枚举三种操作的次数即可

    代码:

    #include <iostream>
    #include <stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<string>
    #include<ctype.h>
    using namespace std;
    #define inf 100000
    int mod(int x)
    {
        if(x>=0)
            return x%10;
        else
            return (10+x%10)%10;
    }
    char s[1010];
    char to[1010];
    int dp[1010][1010];
    int num[3];
    int tmp[3];
    int p[3]= {1,20,400};
    int main()
    {
        while(scanf("%s%s",s+1,to+1)!=EOF)
        {
            memset(dp,0x3f,sizeof(dp));
            dp[0][210]=0;
            int n=strlen(s+1);
            for(int i=1; i<=n; i++)
            {
                for(int j=1; j<400; j++)
                {
                    if(dp[i-1][j]>=inf)
                        continue;
                    for(int k=0; k<2; k++)
                    {
                        num[k]=(j%p[k+1])/p[k];
                    }
                    int cha=mod(to[i]-s[i]-(num[0]-10));
                    for(int a=0; a<=cha; a++)
                    {
                        for(int b=0; a+b<=cha; b++)
                        {
                            int c=cha-a-b;
                            tmp[0]=num[1]-10+b+c;
                            tmp[0]=tmp[0]%10+10;
                            tmp[1]=c+10;
                            dp[i][tmp[0]+tmp[1]*20]=min(dp[i][tmp[0]+tmp[1]*20],dp[i-1][j]+cha);
                        }
                    }
                    cha=10-cha;
                    for(int a=0; a<=cha; a++)
                    {
                        for(int b=0; a+b<=cha; b++)
                        {
                            int c=cha-a-b;
                            tmp[0]=10-(20-num[1]+b+c)%10;
                            tmp[1]=10-c;
                            dp[i][tmp[0]+tmp[1]*20]=min(dp[i][tmp[0]+tmp[1]*20],dp[i-1][j]+cha);
                        }
                    }
                }
            }
            //printf("%d
    ",dp[1][9+9*20]);
            //printf("%d
    ",dp[2][9+10*20]);
            printf("%d
    ",dp[n][210]);
        }
        return 0;
    }
    View Code


     

    1005:

    题意:

    一个图有n个点,初始在点1,每次加满油后最多能跑d距离,现在点1有一个加油站,问环游全程回到1需要怎么建加油站

    第i点建加油站的话 二进制第i位为1,答案要满足建造情况的二进制数最小

    做法:

    贪心,要尽量要高位的点不建,先假设所有点建了,再从大到小考虑,如果当前点不建也能满足需求,则把该点加油站删去

    因为要考虑连通性所以判断是否满足需求要用bfs

    代码:

    #include <iostream>
    #include <stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<string>
    #include<ctype.h>
    #include<queue>
    #include<math.h>
    using namespace std;
    int g[150][150];
    int x[150];
    int y[150];
    int vi[150];
    int vis[150];
    int n,d;
    queue<int>q;
    int check()
    {
        memset(vis,0,sizeof(vis));
        while(!q.empty())
            q.pop();
        q.push(0);
        while(!q.empty())
        {
            int now=q.front();
            vis[now]=1;
            q.pop();
            for(int i=0;i<n;i++)
            {
                if(!vis[i])
                {
                    if(g[now][i]<=d/2)
                    {
                        vis[i]=1;
                    }
                    if(g[now][i]<=d&&vi[i])
                    {
                        q.push(i);
                    }
                }
            }
        }
        for(int i=0;i<n;i++)
        {
            if(vis[i]==0)
                return 0;
        }
        return 1;
    }
    int main()
    {
        //freopen("in.txt","r",stdin);
        while(scanf("%d%d",&n,&d)!=EOF)
        {
            for(int i=0;i<n;i++)
            {
                vi[i]=1;
            }
            for(int i=0; i<n; i++)
            {
                scanf("%d%d",x+i,y+i);
            }
            for(int i=0; i<n; i++)
            {
                for(int j=0; j<n; j++)
                {
                    g[i][j]=ceil(sqrt((double)((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]))));
                }
            }
            if(check()==0)
            {
                puts("-1");
                continue;
            }
            for(int i=n-1; i>=1; i--)
            {
                vi[i]=0;
                if(!check())
                    vi[i]=1;
            }
            int f=1;
            for(int i=n-1; i>=0; i--)
            {
                if(vi[i])
                {
                    printf("1");
                    f=0;
                }
                else
                {
                    if(f==0)
                        printf("0");
                }
            }
            puts("");
    
        }
        return 0;
    }
    View Code

    1006:

     题意: n个字符串,对于每一个子串可以表示为一个数字, 求所有子串的数字和相加对2012取模,, 相同数字只算一次。

    这题可以先把n个字符串用一个没有出现过的字符隔开连起来。然后求sa, lcp。

    我们可以先看一个简单的例子。

    s = 12345

    num[1] = 1             sum[1] = 1

    num[2] = 12           sum[2] = 1 + 12

    num[3] = 123         sum[3] = 1 + 12 + 123

    num[4] = 1234       sum[4] = 1 + 12 + 123 + 1234 

    num[5] = 12345     sum[5] = 1 + 12 + 123 + 1234 + 12345

    如果求[3, 4]  , 只需要 sum[5] - sum[2] - num[2] * (10 + 100 + 1000);

    判重时 只要从 i+ lcp[rank[i]]  开始算就可以了,,因为公共前缀那一部分 在前面已经算了。

    上代码。。

      1 #include <set>
      2 #include <map>
      3 #include <cmath>
      4 #include <ctime>
      5 #include <queue>
      6 #include <stack>
      7 #include <cstdio>
      8 #include <string>
      9 #include <vector>
     10 #include <cstdlib>
     11 #include <cstring>
     12 #include <iostream>
     13 #include <algorithm>
     14 using namespace std;
     15 typedef unsigned long long ull;
     16 typedef long long ll;
     17 const int inf = 0x3f3f3f3f;
     18 const double eps = 1e-8;
     19 const int mod = 2012;
     20 const int maxn = 2e5+100;
     21 int sum [maxn], num[maxn];
     22 string s;
     23 int sa[maxn], Rank[maxn], tmp[maxn], lcp[maxn];
     24 int k, len;
     25 bool cmp(int i, int j)
     26 {
     27     if (Rank[i] != Rank[j])
     28         return Rank[i] < Rank[j];
     29     else
     30     {
     31         int x = (i+k <= len ? Rank[i+k] : -1);
     32         int y = (j+k <= len ? Rank[j+k] : -1);
     33         return x < y;
     34     }
     35 }
     36 void build_sa()
     37 {
     38     for (int i = 0; i <= len; i++)
     39     {
     40         sa[i] = i;
     41         Rank[i] = (i < len ? s[i] : -1);
     42     }
     43     for (k = 1; k <= len; k *= 2)
     44     {
     45         sort (sa,sa+len+1,cmp);
     46         tmp[sa[0]] = 0;
     47         for (int i = 1; i <= len; i++)
     48         {
     49             tmp[sa[i]] = tmp[sa[i-1]] + (cmp(sa[i-1],sa[i])? 1 : 0);
     50         }
     51         for (int i = 0; i <= len; i++)
     52             Rank[i] = tmp[i];
     53     }
     54 }
     55 
     56 void Get_lcp()
     57 {
     58     for (int i = 0; i < len; i++)
     59         Rank[sa[i]] = i;
     60     int h = 0;
     61     lcp[0] = 0;
     62     for (int i = 0; i < len; i++)
     63     {
     64         int j = sa[Rank[i]-1];
     65         if (h > 0)
     66             h--;
     67         for (; h+i < len && h+j < len; h++)
     68             if (s[i+h] != s[j+h])
     69                 break;
     70         lcp[Rank[i]] = h;
     71     }
     72 }
     73 bool isdigit(char &ch)
     74 {
     75     return ch >= '0' && ch <= '9';
     76 }
     77 int vec[maxn], board[maxn], tot;
     78 int SUM[maxn];
     79 int solve (int l, int r)
     80 {
     81     if (l > r)
     82         return 0;
     83     int res ;
     84     res = sum[r] - sum[l-1];
     85     res = ((res%mod)+mod)%mod;
     86     res -= num[l-1] * SUM[r-l+1];
     87     res = ((res%mod)+mod)%mod;
     88     return ((res%mod)+mod)%mod;
     89 }
     90 int main()
     91 {
     92 #ifndef ONLINE_JUDGE
     93     freopen("in.txt","r",stdin);
     94 #endif
     95     int n;
     96     SUM[1] = 10;
     97     for (int i = 2; i < maxn; i++)
     98     {
     99         SUM[i] = (SUM[i-1] + 1) * 10 % mod;
    100     }
    101     while (~scanf ("%d", &n))
    102     {
    103         s = "";
    104         tot = 0;
    105         memset(sum, 0, sizeof(sum));
    106         memset(num, 0, sizeof(num));
    107         for (int i = 0; i < n; i++)
    108         {
    109             string tmp;
    110             cin >> tmp;
    111             s += tmp + "#";
    112         }
    113         len = s.size();
    114         int val = 0;
    115         for (int i = 0; i < len; i++)
    116         {
    117             if (s[i] != '#')
    118             {
    119                 val = (val * 10 + s[i] - '0') % mod;
    120                 num[i] = val;
    121                 sum[i] = (sum[i-1] + num[i]) % mod;
    122                 board[i] = tot;
    123             }
    124             if (s[i] == '#')
    125             {
    126                 vec[tot++] = i;
    127                 num[i] = val;
    128                 sum[i] = sum[i-1] + val;
    129             }
    130         }
    131         build_sa();
    132         Get_lcp();
    133         int ans = 0;
    134         for (int i = 0; i < len; i++)
    135         {
    136             int t1 = i + lcp[Rank[i]];
    137             if (s[i] == '0')
    138                 continue;
    139             if (isdigit(s[i]) && i+lcp[Rank[i]] < vec[board[i]])
    140             {
    141                 int t2 = vec[board[i]] -1;
    142                 int ans1 = solve(i, t2);
    143                 int ans2 = solve(i , t1-1);
    144                 ans = (ans + solve(i, t2) - solve(i, t1-1)) % mod;
    145                 if (ans < 0)
    146                     ans += mod;
    147             }
    148         }
    149         printf("%d
    ", ans%mod);
    150     }
    151     return 0;
    152 }
    View Code

    1008:

    题意:

    很简单的高中数学签到题

    思路:

    代码:

    #include <set>
    #include <map>
    #include <cmath>
    #include <ctime>
    #include <queue>
    #include <stack>
    #include <cstdio>
    #include <string>
    #include <vector>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    typedef unsigned long long ull;
    typedef long long ll;
    const int inf = 0x3f3f3f3f;
    const double eps = 1e-8;
    double x, y;
    double p, q;
    double fun1()
    {
        double a1 = q*p*p*(x+y);
        double a2 = q*p*(1-p)*x;
        double a3 = q*p*(1-p)*y;
        double a4 = (1-q)*x;
        return a1+a2+a3+a4;
    }
    double fun2()
    {
        double a1 = (1-q) * p*p*(x+y);
        double a2 = (1-q)*p*(1-p)*x;
        double a3 = (1-q)*p*(1-p)*y;
        double a4 = (q)*y;
        return a1+a2+a3+a4;;
    }
    int main()
    {
    
        int t;
        cin>>t;
        while (t--)
        {
            scanf ("%lf%lf%lf%lf",&x, &y, &p, &q);
            if (fun1() > fun2())
            {
                printf("tiger %.4f
    ", fun1());
            }
            else
                printf("wolf %.4f
    ", fun2());
        }
        return 0;
    }
    View Code

    1011:

  • 相关阅读:
    TSP-UK49687
    维度建模的基本原则
    差分约束系统
    随机过程初步
    随机过程——维纳过程
    Xilinx FPGA复位信号设计
    10 Row Abacus
    Python
    FX2LP与FPGA的简单批量回环
    DFT公式的一个简单示例
  • 原文地址:https://www.cnblogs.com/oneshot/p/4398126.html
Copyright © 2011-2022 走看看