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("\n");
}
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\n",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\n",ans);
    }
}
posted @ 2018-08-10 14:17  冥想选手  阅读(692)  评论(0编辑  收藏  举报