zoukankan      html  css  js  c++  java
  • 2017ACM/ICPC亚洲区沈阳站-重现赛

    HDU 6222 Heron and His Triangle

     

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=6222

    思路: 打表找规律+大数运算

    首先我们可以打个表暴力跑出前几个满足题意的T

    打表代码:

    #include<bits/stdc++.h>
    using namespace std;
    bool fun(double n) {
           if(abs(round(n) - n) < 0.000000000000001)
            return 1;
           return 0;
    }
    
    int main()
    {
        for(int i = 2;i <= 10000000;i ++){
            double num = (i+1)*sqrt(3*(i-1)*(i+3))/4;
            if(fun(num))
                cout<<i+1<<endl;
        }
    }

    打出表后会得到: 4,14,52,194,724等数据。。。经过推导我们会得到他们之间的公式: a[i] = a[i-1]*4-a[i-2],然后我们用大数模板去跑这串公式就好了

    实现代码:

    #include<bits/stdc++.h>
    using namespace std;
    /*bool fun(double n) {
           if(abs(round(n) - n) < 0.000000000000001)
            return 1;
           return 0;
    }
    
    int main()
    {
        for(int i = 2;i <= 10000000;i ++){
            double num = (i+1)*sqrt(3*(i-1)*(i+3))/4;
            if(fun(num))
                cout<<i+1<<endl;
        }
    }*/
    string Mult(string s,int x)  //大数乘以整形数
    {
        reverse(s.begin(),s.end());
        int cmp=0;
        for(int i=0;i<s.size();i++)
        {
            cmp=(s[i]-'0')*x+cmp;
            s[i]=(cmp%10+'0');
            cmp/=10;
        }
        while(cmp)
        {
            s+=(cmp%10+'0');
            cmp/=10;
        }
        reverse(s.begin(),s.end());
        return s;
    }
    
    string sub(string a,string b)
    {
        string c;
        bool ok=0;
        int len1=a.length();
        int len2=b.length();
        int len=max(len1,len2);
        for(int i=len1;i<len;i++)
            a="0"+a;
        for(int i=len2;i<len;i++)
            b="0"+b;
        if(a<b)
        {
            string temp=a;
            a=b;
            b=temp;
            ok=1;
        }
        for(int i=len-1;i>=0;i--)
        {
            if(a[i]<b[i])
            {
                a[i-1]-=1;
                a[i]+=10;
            }
            char temp=a[i]-b[i]+'0';
            c=temp+c;
        }
        int pos=0;
        while(c[pos]=='0' && pos<len) pos++;
        if(pos==len) return "0";
        if(ok) return "-"+c.substr(pos);
        return c.substr(pos);
    }
    string s1[61];
    
    int main()
    {
        int t;
        cin>>t;
        string s;
        s1[1] = "4";s1[2] = "14";
        for(int i = 3;i <= 60;i ++)
            s1[i] = sub(Mult(s1[i-1],4),s1[i-2]);
        while(t--){
        cin>>s;
        for(int i = 1;i <= 60;i ++)
            if(s1[i].size() > s.size()||(s1[i].size()==s.size()&&s1[i]>=s)){
            cout<<s1[i]<<endl;
            break;
            }
        }
        return 0;
    }

    HDU 6223  Infinite Fraction Path

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=6223

    思路:bfs + 剪枝

    算比较容易的bfs,一直没怎么写bfs,差点写自闭了。。。。调了半天才过。

    实现代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int M = 4e5+10;
    #define ll long long
    int vis[M];  //判断当前点是否被访问过了
    int n,a[M],top; 
    int cnt[M];  //储存当前层被标记点的下标
    int mx[M];  //每一层的最大值
    struct node{
        long long id;
        int val,step;
    };
    //优先排步数小的,步数相等优先值大的
    bool operator < (node a,node b){
        if(a.step == b.step) return a.val < b.val;
        return a.step > b.step;
    }
    priority_queue<node> q;
    void bfs(){
        int last = -1;
        while(!q.empty()){
            node now = q.top();
            q.pop();
            if(now.step != last) {  //已经步入下一层了清空上一层的标记
                last = now.step;
                while(top) vis[cnt[--top]] = 0;
            }
            //限制条件剪枝
            if(now.step == n) continue;
            if(vis[now.id]) continue;  //当前点被访问过了,跳过
            if(mx[now.step] > now.val) continue; //当前点小于这一层的最大值,跳过
            //维护标记
            cnt[top++] = now.id;
            vis[now.id] = 1; mx[now.step] = now.val;
            //将下一个点扔进队列中
            node next;
            next.id = (now.id*now.id+1)%n;;
            next.val = a[next.id];
            next.step = now.step+1;
            q.push(next);
        }
        for(int i = 0;i < n;i ++) printf("%d",mx[i]);
        for(int i = 0;i <= n;i ++) mx[i] = 0;
       printf("
    ");
    }
    char s[M];
    int main()
    {
    
        int maxx,t;
        scanf("%d",&t);
        int t1 = t;
        while(t--){
            top = 0;
            scanf("%d",&n);
            maxx = 0;
            scanf("%s",s);
            for(int i = 0;i < n;i ++){
                a[i] = s[i]-'0';
                maxx = max(maxx,a[i]);
            }
            mx[0] = maxx;
            for(int i = 0;i < n;i ++)
            if(a[i] == maxx){
                node now; now.id = i;now.val = a[i],now.step = 0;
                q.push(now);
            }
            printf("Case #%d: ",t1-t);
            bfs();
        }
        return 0;
    }

     

    HDU 6225  Little Boxes

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=6225

    大数加法

    签到题

    实现代码:

    #include<bits/stdc++.h>
    using namespace std;
    
    string sum(string s1,string s2)
    {
        if(s1.length()<s2.length())
        {
            string temp=s1;
            s1=s2;
            s2=temp;
        }
        int i,j;
        for(i=s1.length()-1,j=s2.length()-1;i>=0;i--,j--)
        {
            s1[i]=char(s1[i]+(j>=0?s2[j]-'0':0));   
            if(s1[i]-'0'>=10)
            {
                s1[i]=char((s1[i]-'0')%10+'0');
                if(i) s1[i-1]++;
                else s1='1'+s1;
            }
        }
        return s1;
    }
    int main()
    {
        int n;
        string x;
        cin>>n;
        for(int i = 1;i <= n;i ++){
            string ans = "0";
            for(int j = 1;j <= 4;j ++){
                cin>>x;
                ans = sum(ans,x);
            }
            cout<<ans<<endl;
        }
        return 0;
    }

    HDU  6227  Rabbits

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=6227

    思路: 求兔子最多跳的次数,排个序,两种情况取最大的:

    第一种: 第二小的和最大的之间距离之差减去中间已经有位置的值

    第二种: 倒着跳,第二大的和最小的距离之差减去中间已经有位置的值

    签到题

    实现代码:

    #include<bits/stdc++.h>
    using namespace std;
    int a[20200];
    int main()
    {
        int t,n,x;
        scanf("%d",&t);
        while(t--){
            scanf("%d",&n);
            for(int i = 1;i <= n;i ++)
                scanf("%d",&a[i]);
            sort(a+1,a+1+n);
            int ans = max(a[n]-a[2]-n+2,a[n-1]-a[1]-n+2);
            printf("%d
    ",ans);
        }
        return 0;
    }

    HDU  6228 Tree

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=6228

    思路:

    要求公共子集最大,我们肯定是优先选择距离大的两点染成相同的颜色(因为要留位置给其他颜色),要达到公共边最多,那么我们可以先对边进行分析,如果一条边左边结点的子树大于k,右边结点的子树也大于k那么这条边可以成为公共子集的一条因为我们是要求最大的,根据最优策略,肯定要将他加进最大公共子集中,找到这种边+1就好了。

    实现代码;

    #include<bits/stdc++.h>
    using namespace std;
    const int M = 1e5 + 10;
    vector<int>g[M];
    int ans,n,k,siz[M];
    void dfs(int u,int fa){
        siz[u] = 1;
         for(int i = 0;i < g[u].size();i ++){
            int v = g[u][i];
            if(v == fa) continue;
            dfs(v,u);
            siz[u] += siz[v];
            if(siz[v] >= k&&(n-siz[v])>=k) ans++;
         }
    }
    
    int main()
    {
        int t,x,y;
        scanf("%d",&t);
        while(t--){
            memset(siz,0,sizeof(siz));
            scanf("%d%d",&n,&k);
            for(int i = 1;i <= n;i ++)
                g[i].clear();
            for(int i = 1;i < n;i ++){
                scanf("%d%d",&x,&y);
                g[x].push_back(y);
                g[y].push_back(x);
            }
            ans = 0;
            dfs(1,-1);
            printf("%d
    ",ans);
        }
    }
  • 相关阅读:
    两次动态输入和while的结合使用
    索引切片步长
    12.⽤户登陆(三次输错机会)且每次输错误时显示剩余错误次数(提示:使⽤字符串格式化)
    输出1-100的所以奇数或偶数
    求1-2+3-4+5 ... 99的所有数的和
    求1-100所有数的和
    三次登录机会
    while输入12345689
    while和格式化输出的复合使用
    44
  • 原文地址:https://www.cnblogs.com/kls123/p/9451052.html
Copyright © 2011-2022 走看看