数数

【问题描述】

给定n,m,k都是小于等于10001的正整数,输出给定的n个数中,其m次幂能被k整除的数的个数。

【输入格式】

有两行组成,第一行是三个整数n,m,k

第二行是n个正整数 都不超过10001

【输出格式】

输出满足条件的数的个数

【样例输入】count.in

3 2 50

9 10 11

【样例输出】count.out

1

#include <cstdio>
const int prime[25]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97};
int n,m,k;
int c[25];
int main(){
    freopen("count.in","r",stdin);
    freopen("count.out","w",stdout);
    scanf("%d%d%d",&n,&m,&k);
    int j=k;
    for (int i=0;i<25;i++){
        while ((j % prime[i])==0){
              j/=prime[i];
              c[i]++;
        }
    }
    if (j!=1) k=j;else k=1;
    for (int i=0;i<25;i++){
        if (c[i] % m==0) c[i]/=m;else c[i]=c[i]/m+1;
        for (int j=1;j<=c[i];j++) k*=prime[i];
    }
    m=0;
    for (int i=1;i<=n;i++){
        int x;
        scanf("%d",&x);
        if (!(x % k)) m++;
    }
    printf("%d\n",m);
    return 0;
}
最长链

【问题描述】

给定一棵有N个节点的树,求每个节点到其他节点的最大距离

【输入格式】

输入第一行是一个自然数 N (N<=10000), 接下来 (N-1) 行描述:

第i行包含两个自然数 , 表示编号为i的节点连接到的节点编号和这条网线的长度..距离总长不会超过10^9. 每行中的两个数字用空格隔开.

【输出格式】

输出包含N行. 第i行表示对于离编号为i的节点最远的节点与该节点的距离Si(1<=i<=N).

【样例输入】length.in

3

1 1

1 2

【样例输出】length.out

2

3

3

【数据范围】

30% N<=100

100%N<=10000

 

#include <cstdio>
#include <cstring>
#include <iostream>
#define INF 214748364
struct edge{
       int x,w,next;
}e[20010],e2[20010];
int tot2,tot;
int n;
bool v[20010];
int k2[20010];
int fa[20010];
int w[20010];
int k[20010];
int f[20010][3];
int max(int a,int b){return a>b?a:b;}
void add2(int x,int y,int z){
     e2[++tot2].x=y;
     e2[tot2].w=z;
     e2[tot2].next=k2[x];
     k2[x]=tot2;
}
void add(int x,int y,int z){
     e[++tot].x=y;
     e[tot].w=z;
     e[tot].next=k[x];
     k[x]=tot;
}
void build(int x){
     v[x]=true;
     for (int t=k2[x];t;t=e2[t].next){
         if (!v[e2[t].x]){
                          add(x,e2[t].x,e2[t].w);
                          fa[e2[t].x]=x;
                          w[e2[t].x]=e2[t].w;
                          build(e2[t].x);
         }
     }
}
void dp1(int x){
     for (int t=k[x];t;t=e[t].next){
         dp1(e[t].x);
         if (f[x][1]<f[e[t].x][1]+e[t].w){
                                          f[x][2]=f[x][1];
                                          f[x][1]=f[e[t].x][1]+e[t].w;
         }else if (f[x][2]<f[e[t].x][1]+e[t].w){
               f[x][2]=f[e[t].x][1]+e[t].w;
         }
     }
}
void dp2(int x){
     if (fa[x]!=-1){
                    if (f[fa[x]][1]==f[x][1]+w[x])
                         f[x][0]=max(f[fa[x]][0],f[fa[x]][2])+w[x];
                    else f[x][0]=max(f[fa[x]][0],f[fa[x]][1])+w[x];
     }
     for (int t=k[x];t;t=e[t].next){
         dp2(e[t].x);
     }
}
int main(){
    freopen("length.in","r",stdin);
    freopen("length.out","w",stdout);
    scanf("%d",&n);
    for (int i=2;i<=n;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        add2(i,x,y);
        add2(x,i,y);
    }
    memset(fa,255,sizeof(fa));
    build(1);
    dp1(1);
    dp2(1);
    for (int i=1;i<=n;i++){
        int ans=max(f[i][0],f[i][1]);
        printf("%d\n",ans);
    }
    return 0;
}
水站

【问题描述】

已知有一个N 层的水站 :

Wi表示未操作之前第i层的已有水量;

Li 表示第i个水站能够维持或者储存的水的重量;

Pi 表示在第i层进行减压放水操作所需的费用.

被压减放水层所储存的所有水都将流向下一层.

如果第 i层的水量比Li大,则这一层也会(自动)减压(不需要任何费用). 

现在想要使最后一层减压(第N级) ,求最少的花费.

这个任务现在交给了你。

【输入格式】

每个输入的第一行包含一个自然数N (1<=N<=15000).

接下来N行每行包含 3 个数 Wi, Li, Pi (0<=Wi,Li,Pi<=15000).

【输出格式】

第一行输出所需的最小费用

第二行若干个整数,从小到大输出必须减压的层的编号。

【样例输入】station.in

3
1000 1000 1
0 1000 2
2 10 100

【样例输出】station.out

3

1 2

Hint:给第一层和第二层减压

【数据范围】

30% N<=5000

100%N<=15000

 

#include <iostream>
#include <cstdio>
#include <queue>
#include <cstdlib>
#include <cstring>
#define INF 214748364
using namespace std;
int n;
int w[15100],l[15100],p[15100];
int sum[15100];
int cost;
int ans=INF,ansi;
typedef struct Heap{
    bool operator <(Heap T)const{
        return T.need<need;
    }
    int need;
    int id;
}Heap;
priority_queue<Heap>Q;
int main(){
    freopen("station.in","r",stdin);
    freopen("station.out","w",stdout);
    scanf("%d",&n);
    for (int i=1;i<=n;i++){
        scanf("%d%d%d",&w[i],&l[i],&p[i]);
    }
    for (int i=n;i>0;i--) sum[i]=sum[i+1]+w[i];
    for (int i=n;i>0;i--){
        cost+=p[i];
        while (!Q.empty() && sum[i]-Q.top().need>0){
              cost-=p[Q.top().id];
              Q.pop();
        }
        Heap t;
        t.id=i;
        t.need=l[i]-w[i]+sum[i];
        Q.push(t);
        if (ans>cost){
                      ans=cost;
                      ansi=i;
        }
    }
    printf("%d\n",ans);
    cost=0;
    for (int i=ansi;i<=n;i++){
        cost+=w[i];
        if (cost<=l[i]){
                        printf("%d ",i);
        }
    }
    return 0;
}
聚会

【问题描述】

小S想要从某地出发去同学k的家中参加一个party,但要有去有回。他想让所用的时间尽量的短。但他又想知道从不同的点出发,来回的最短时间中最长的时间是多少,

这个任务就交给了你。

【输入格式】

第一行三个正整数n,m,k(n是节点个数,m是有向边的条数,k是参加聚会的地点编号)( 1 ≤ N ≤ 1000 ,1 ≤ M ≤ 100,000)

第二行..m+1行每行3个整数x,y,w 代表从x到y需要花w的时间(1 ≤ w≤ 100)

【输出格式】

输出从不同的节点出发的最短时间中最长的时间。

【样例输入】party.in

4 8 2

1 2 4

1 3 2

1 4 7

2 1 1

2 3 5

3 1 2

3 4 4

4 2 3

【样例输出】party.out

10

#include <cstdio>
#include <cstring>
#define INF 2147483647
int n,m,K;
struct node{
       int x,w,next;
}e[101000],e2[101000];
int k[1100];
int k2[1100];
int tot,tot2;
int d[1100];
int d2[1100];
bool v[1100];
int f[1000000];
int max(int a,int b){return a>b?a:b;}
void add(int x,int y,int z){
     e[++tot].x=y;
     e[tot].w=z;
     e[tot].next=k[x];
     k[x]=tot;
}
void add2(int x,int y,int z){
     e2[++tot2].x=y;
     e2[tot2].w=z;
     e2[tot2].next=k2[x];
     k2[x]=tot2;
}
void SPFA(){
     memset(v,0,sizeof(v));
     memset(d,8,sizeof(d));
     d[K]=0;
     v[K]=true;
     int head=0,tail=1;
     f[tail]=K;
     while (head<tail){
           int x=f[++head];
           v[x]=false;
           for (int t=k[x];t;t=e[t].next){
               if (d[e[t].x]>d[x]+e[t].w){
                                          d[e[t].x]=d[x]+e[t].w;
                                          if (!v[e[t].x]){
                                                          v[e[t].x]=true;
                                                          f[++tail]=e[t].x;
                                          }
               }
           }
     }
}
void SPFA2(){
     memset(v,0,sizeof(v));
     memset(d2,8,sizeof(d2));
     d2[K]=0;
     v[K]=true;
     int head=0,tail=1;
     f[tail]=K;
     while (head<tail){
           int x=f[++head];
           v[x]=false;
           for (int t=k2[x];t;t=e2[t].next){
               if (d2[e2[t].x]>d2[x]+e2[t].w){
                                              d2[e2[t].x]=d2[x]+e2[t].w;
                                              if (!v[e2[t].x]){
                                                               v[e2[t].x]=true;
                                                               f[++tail]=e2[t].x;
                                              }
               }
           }
     }
}
int main(){
    freopen("party.in","r",stdin);
    freopen("party.out","w",stdout);
    scanf("%d%d%d",&n,&m,&K);
    for (int i=1;i<=m;i++){
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z);
        add2(y,x,z);
    }
    SPFA();
    SPFA2();
    int ans=0;
    for (int i=1;i<=n;i++){
        if (d[i]+d2[i]<10000000){
                  ans=max(ans,d[i]+d2[i]);
        }
    }
    printf("%d\n",ans);
    return 0;
}