HPU第一次团队赛

D. Tom的战力问题

Tom揍了TAT。
Tom下定决心要战胜
但是在战胜最强的之前,Tom要先打败其他的狗。为此,他打算先收集一下信息。
现在Tom在了得到了一些关于战斗力的小道消息,例如X号狗狗的战力比Y号狗狗的战力高S点。
Tom想知道利用这些消息,能不能判断出某两只狗之间的战力高低?高多少?

输入格式

第一行包含三个整数N,MQN表示狗总数,M表示Tom知道消息的总数,Q表示小Tom想询问的数量。  

以下M行每行三个整数,X,YS。表示X号狗的战力比Y号狗的战力高S点。  

以下Q行每行两个整数,XY。表示Tom想知道X号狗的战力比Y号狗的战力高几点。  
2N1000 
1M,QN 
1X,YN 
1000S1000

数据保证没有矛盾。

输出格式

对于每个询问,如果不能判断出XY高几点输出1。否则输出XY高多少战力点。

样例

input
10 5 3
1 2 10
2 3 10
4 5 -10
5 6 -10
2 5 10
1 10
1 5
3 5
output
-1
20
0
其实就是一个简单的BFS问题。题目中问两个狗之间的站力相差多少,我们可以看成路径问题即A到B的距离为C,B到A的距离为-C,然后跑图,不可到大的话输出-1
 #include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int N=1e3+7;
int n,m,q;

struct stu{
    int a,b;
};
vector<stu >ve[N];
int mark[N];
bool check=false ;
int f=-1;

void bfs(int x,int y){
    memset(mark,0,sizeof(mark));
    queue<stu >que;
    que.push({x,0});
    mark[x]=1;
    while(que.size()){
        stu aa=que.front();
        que.pop();
//        cout<<aa.a<<endl;
        if(aa.a==y){
            f=aa.b;
            break;
        }
        for(int i=0;i<ve[aa.a].size();i++){
            if(mark[ve[aa.a][i].a]==0){
                mark[ve[aa.a][i].a]=1;
                que.push({ve[aa.a][i].a,aa.b+ve[aa.a][i].b});
            }
        }
    }
}


int main(){
    scanf("%d%d%d",&n,&m,&q);
    int x,y,z;
    
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&x,&y,&z);
        ve[x].push_back({y,z});
        ve[y].push_back({x,-z});
    }
    
    
    while(q--){
         f=-1;
         int x,y;
         scanf("%d%d",&x,&y);
         bfs(x,y);
         printf("%d\n",f);
    } 
    
    return 0;
} 

E  Tom的函数求值

众所周知,Tom不会递归,但是今天他突然顿悟了!并且凭借自己的能力写出了下面这段代码:

int F(int m,int n) { if(!m) return n+1; if(!n&&m) return F(m-1,1); if(m&&n) return F(m-1,F(m,n-1)); } 

现在,他想让你根据这个函数来解决问题

输入格式

单组输入,每组一行,有两个整数mn(0m3,0n27)

输出格式

请输出上面代码的运行结果

样例

input
1 1
output
3
input
0 1
output
2

提示

如果不知道怎么做的话,不妨试试直接把代码复制粘贴进去吧٩̋(ˊ•͈ ꇴ •͈ˋ)و

对于这种类型的题目,我们可以先运行一下它给出的代码,然后输出一些值,在找规律。

//int F(int m,int n)
//{
//    if(!m)
//        return n+1;
//    if(!n&&m)
//        return F(m-1,1);
//    if(m&&n)
//        return F(m-1,F(m,n-1));
//}
#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
// m==0  n+1;
// m==1  2 3 4
// m==2  3 5 7
// m==3  5 13 29
ll f(ll x){
    if(x==0) return 5;
    else return 2*f(x-1)+3;
}
int main(){
    ll a,b;
    scanf("%lld %lld",&a,&b);
    if(a==0) printf("%d",b+1);
    else if(a==1) printf("%d\n",b+2);
    else if(a==2) printf("%d\n",2*b+3); 
    else if(a==3) printf("%lld\n",f(b));
    return 0;
} 

FTom的约会

XX协会又要迎来新的成员了。

这次的妹子颇多,足足有n人之多(1n106),她们每个人的学号都是1018 内的一个正整数。

Jerry 早早地就掌握了她们每个人的学号,并且知道她们之中有一个人和Tom约会去了!

Jerry 统计了在场所有妹子的学号,他想知道,哪个人没来?

输入格式

第一行是一个整数n,代表一共有n只妹纸

以下n行每行一个整数,代表每只妹纸的学号

接下来一个空行

以下n1行每行一个整数,代表每只来了的妹纸的学号

输出格式

输出没来的妹纸的学号。

样例

input
3
10061061
10061023
10061201

10061023
10061201
output
10061061

提示

开头别想着抢一血,稳着跟榜做题,很多队伍过的题自己卡住了别慌,肯定不是特别难的算法,多换几个思路,上个厕所调整一下状态,总之,心态要好~
~~ 以上都是废话 ~~

看到这个题目,觉得用map比较好,但是TLE了,,用map没TLE的是卡过去的,这里可以开个两个数组,存完值后进行排序,找到第一个不向等的,就可以退出了,

也可以用无序字典

代码1:

#include<iostream>
#include<cstdio>
#include<unordered_map>
using namespace std;
typedef long long ll;
unordered_map<ll,int >mp;
unordered_map<ll,int>::iterator it;
int main(){
    int t;
    cin>>t;
    int t1=t-1;
    while(t--){
        ll x1;
        scanf("%lld",&x1);
        mp[x1]++;
    }
    while(t1--){
        ll y;
        scanf("%lld",&y);
        mp[y]++;
    }
    for(it=mp.begin();it!=mp.end();it++){
        if(it->second==1){
            printf("%lld\n",it->first);
            break;
        } 
    }
    return 0;
} 

代码2:

#include<cstdio>
#include<algorithm> 
#include<vector>
using namespace std;
typedef long long ll; 
const int     N=1e6+7;
ll p[N];
ll p2[N];
int main(){
    int t;
    scanf("%d",&t);
    ll x;
    for(int i=1;i<=t;i++){
        scanf("%lld",&p[i]);
    }
    for(int i=1;i<=t-1;i++){
        scanf("%lld",&p2[i]);
    }
    sort(p+1,p+1+t);
    sort(p2+1,p2+t);
    bool f=false ;
    for(int i=1;i<=t-1;i++){
        if(p[i]!=p2[i]){
            f=true;
            printf("%lld",p[i]);
            break; 
        }
    }
    if(!f) printf("%lld",p[t]);
    
    
    return 0;
} 

G. Tom爬楼梯

Jerry 跑到了二楼,现在Tom面临的是一个n阶的楼梯,由于Tom的腿比较短,因此它一次只能爬1阶或2阶,机智的Jerry破坏掉了m阶楼梯,也就是说Tom无法踩在这m阶楼梯上,现在Tom想知道他有多少种方案能爬到第n阶楼梯。由于答案很大,输出方案数对109+7取模的结果。

输入格式

第一行输入一个T代表有T组输入,对于每组输入:
第一行输入n,m,第二行输入m个数,第i个数ai代表第ai阶楼梯被破坏了。
(1T,m10,1n1000,1ain)

输出格式

对于每组输入,输出方案数对109+7取模的结果。

样例

input
3
1 1
1
8 1
1
10 2
1 2
output
0
13
0
 被这个题卡了好久,一开始的想法是计算每一个阶段的值,然后再相乘,但是不好写。。而且数据很大。。
题解:用两个数组,第一个记录每个坏掉的楼梯,第一个记录两个楼梯之间正常楼梯的个数,这里注意开头要特殊处理。开头要保存正常楼梯个数加1。
递推式:dp[1]=1,dp[2]=1.dp[n]=dp[n-1]+dp[n-2];
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;

ll dp[1000+7];
ll arr[1000+7];
ll arr2[1000+7];

void inint(){
    dp[1]=1;
    dp[2]=1;
    for(int i=3;i<=1000;i++){
        dp[i]=(dp[i-1]%mod+dp[i-2]%mod)%mod; 
    }
}

int main(){
    inint();
    int t;
    cin>>t;
    while(t--){
        ll a,b1;
        scanf("%lld%lld",&a,&b1);
        for(int i=1;i<=b1;i++){
            scanf("%lld",&arr[i]);
        }
        sort(arr+1,arr+1+b1);
//         if(arr[b1]==a){
//             puts("0");
//             continue ;
//         }
        int pos=0;
        arr2[pos++]=arr[1];
        for(int i=2;i<=b1;i++){
            arr2[pos++]=arr[i]-arr[i-1]-1;
        }
        arr2[pos++]=a-arr[b1];
        ll ans=1;
        for(int i=0;i<pos;i++){
            ans=(ans%mod*dp[arr2[i]]%mod)%mod;
        }
        cout<<ans<<endl;
    }
    
    return 0;
}

I. Jerry的数学题

Tom自称是数学天才,无法忍受的Jerry 给 Tom 出了一道题,已知a,b,求解下列方程:

{lcm(x,y)=agcd(x,y)=b

Tom顿时傻眼了,现在只有你能来帮他挽回颜面了,快来帮帮它吧。

输入格式

第一行输入一个T代表有T组输入。
每组输入包含两个正整数a,b
(1T100,1a,b10000)

输出格式

对于每组输入,每行输出一组x,y,如果有多组,则输出x最小的,x,y中间用空格隔开。如果无解输出1

样例

input
3
100 50
3 3
6 7
output
50 100
3 3
-1
#include<bits/stdc++.h>
using namespace std;

int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        int a,b;
        scanf("%d%d",&a,&b);
        int x=a*b;
        bool check=false ;
        for(int i=b;i<=a;i+=b){
            int y=x/i;
            if(x%i==0&&__gcd(i,y)==b){
                check=true;
                if(y<i) swap(y,i);
                printf("%d %d\n",i,y);
                break ; 
            }
        }
        if(!check) puts("-1");
    }
    
    return 0;
}

J. Jerry的题

Jerry给Tom出了一道题,题目是这样的:
**给出一棵n个节点的树,节点编号为1-n(根节点编号为1),每一个节点作为根节点与他所有的子孙节点形成一棵子树,而这棵子树包含节点的数量,称作子树的Size。

例如:

1─2─4─5
└─3

其中节点5的子树只包括节点5,Size = 1。节点4的子树包括节点4,5,Size = 2。节点1的子树包括节点1,2,3,4,5,Size = 5。

求以所有节点为根的子树的Size之和。上面例子中,节点1到5,对应的Size分别为5,3,1,2,1,所有Size的和 = 5 + 3 + 1 + 2 + 1 = 12

输入格式

第一行:1个数n(1 < n <= 10000),表示树的节点数量。
后面n-1行:每行2个数x y,表示节点x是节点y的父节点(1 <= x, y <= n)。

输出格式

输出1个数,表示以所有节点为根的子树的Size之和。

样例

input
4
1 2
1 3
2 4
output
8
 这个题目也是一个简单的BFS,我们只要记录每个点可以到达的 点的个数就可以了
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int N=1E5+7;
vector<int >ve[N];
int step[N];
bool mark[N];
int ans=1;
void bfs(int x){
    memset(mark,0,sizeof(mark));
    queue<int>que;
    que.push(x);
    mark[x]=1;
    step[x]=0;
//    cout<<"x:"<<x<<endl;
    while(que.size()){
        int t=que.front();
        que.pop(); 
        for(int i=0;i<ve[t].size();i++){
//            cout<<ve[t][i]<<"++"<<endl;
//            ans++;
            if(mark[ve[t][i]]==0){
                ans++; 
                mark[ve[t][i]]=1;
                step[ve[t][i]]=step[t]+1;
                que.push(ve[t][i]);
            }
        }
    }
}


int main(){
    int t;
    cin>>t; 
    int x,y;
    for(int i=1;i<=t-1;i++)
    {
        cin>>x>>y;
        ve[x].push_back(y);
    }
    long long sum=0;
    for(int i=1;i<=t;i++){
        ans=1;
        bfs(i);
        sum+=1ll*ans;
    }
    cout<<sum<<endl;
    return 0;
}

L. Jerry的食粮

公元9102年,Tom不再追逐Jerry,因为Tom的主人已经从China进口了很多猫粮,并且还有了智能抓老鼠机器。
Jerry无处可躲,只能露宿街头。Tom不再缺乏食粮,但是可怜的小Jerry仍然还饥肠辘辘。
这一天,小Jerry实在是饿坏了,再不吃点儿东西,他可能就横死街头了,于是,他想到了他的老朋友Tom,
Tom这个糟老头子可是坏得很呀,他给小Jerry出了一个问题,做出来这个问题,小Jerry就能获得糟老头子Tom 
赞助的补给!!!只有伟大的团队可以帮得了Jerry,并将获得荣耀之光,你们能帮可怜的Jerry获得补给吗?
给定一个正整数n,求至少两个正整数使得他们的lcm(最小公倍数)为n,且这些正数的和最小,输出这个最小和。

输入格式

第一行一个整数T1T1e4
接下来T行,每行一个正整数n1n2311

输出格式

输出T行,每行输出”Case #: “(不包括“”),#表示第#组数据,后面跟题目要求的答案,具体输出可参考样例

样例

input
3
12
10
5
output
Case 1: 7
Case 2: 7
Case 3: 6
分解质因子,然后记录每个质因子构成的值,最后累加就好了,但是注意,,如果他的质因子个数只有一个,或者他是质数的话直接输出n+1
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=1e6+7;
int prime[N]={1,1,0};
ll pre[N];
void f_prime(){
    int sum=0;
    for(int i=2;i<=N;i++){
        if(prime[i]==0){
            pre[sum++]=i; 
            for(int j=i+i;j<=N;j+=i){
                prime[j]=1;
            }
        }
    }
}

int main(){
    f_prime();
    int t;
    int k=0;
    cin>>t;
    while(t--){
        k++;
        ll n;
        scanf("%d",&n);
        ll n1=n;
        printf("Case %d: ",k);
        if(n==1){
            printf("2\n");
            continue ;
        }
        ll m=sqrt(n+1);
        ll ans=0;
        int x=0;
        for(int i=0;pre[i]<=m;i++){
            ll sum=1;
            if(n%pre[i]==0){
                x++;
                while(n%pre[i]==0){
                    sum*=pre[i];
                    n/=pre[i];
                }
                ans+=sum;
            }
        }
        if(n>1){
            x++;
            ans+=n;
        }
        if(x>1) {
            printf("%lld\n",ans);
        }
        else {
            printf("%lld\n",1+n1);
        }
    }
    return 0;
} 


猜你喜欢

转载自www.cnblogs.com/Accepting/p/11396742.html
今日推荐