zoukankan      html  css  js  c++  java
  • 【寒假集训系列DAY3】

    DAY2的坑之后会补上

    DAY3

    今天暴力分拿的还是不错的...60+30+25=115,但还是太弱了呀,每题都只会暴力(话说第3题直接输-1给了15分,本以为只会给5分,然后打了半个小时的爆搜...)

    T1:Simple (图样图森破?)

    【问题描述】
    对于给定正整数 n,m,我们称正整数 c 为好的,当且仅当存在非
    负整数 x,y,使得 n*x+m*y=c。
    现在给出多组数据,对于每组数据,给定 n,m,q,求[1,q]内有
    多少个正整数不是好的。
    【输入格式】
    第一行,一个整数 T 表示数据组数。
    接下来每行三个数,分别表示 n,m,q,即一组询问。
    【输出格式】
    对于每组数据,输出一行表示答案。

    考试的时候打了一个暴力,妥妥的60分...

    交卷前问了一下Venus巨佬,然而他说是一道DP题,感觉瞬间明白了什么,其实就是一道简单的DP啊,但来不及改了...

    思路:DP(当然数学方法也可以,但是好烦啊...)类似于背包?反正暴力填表就好了..把“好的数”求出来,然后减一下就好了

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define int long long
     6 using namespace std;
     7 inline int read(){
     8     char chr=getchar();    int f=1,ans=0;
     9     while(!isdigit(chr)) {if(chr=='-') f=-1;chr=getchar();}
    10     while(isdigit(chr))  {ans=(ans<<3)+(ans<<1);ans+=chr-'0';chr=getchar();}
    11     return ans*f;
    12 }
    13 void write(int x){
    14     if(x<0) putchar('-'),x=-x;
    15     if(x>9) write(x/10);
    16     putchar(x%10+'0');
    17 }
    18 int n,m,h,f[2000005];
    19 signed main(){
    20     freopen("simple.in","r",stdin);
    21     freopen("simple.out","w",stdout);
    22     int t=0;
    23     t=read();
    24     for(int i=1;i<=t;i++){
    25          n=read(),m=read(),h=read();
    26          memset(f,-1,sizeof(f));
    27          f[0]=0; int last=0;
    28          for(int j=1;f[(last+m)%n]==-1;j++) f[(last+m)%n]=f[last]+m,last=(last+m)%n;
    29          int ans=0;
    30           for(int i=0;i<n;i++)
    31                if(f[i]!=-1&&f[i]<=h) ans+=(h-f[i])/n+1;
    32           printf("%lld
    ",h-ans+1);
    33     }
    34     return 0;
    35 }

    T2:Walk 

    【问题描述】
    给定一棵 n 个节点的树,每条边的长度为 1,同时有一个权值
    w。定义一条路径的权值为路径上所有边的权值的最大公约数。现在
    对于任意 i∈[1,n],求树上所有长度为 i 的简单路径中权值最大的
    是多少。如果不存在长度为 i 的路径,则第 i 行输出 0。
    【输入格式】
    第一行,一个整数 n,表示树的大小。
    接下来 n-1 行,每行三个整数 u,v,w,表示 u,v 间存在一条权值
    为 w 的边。
    【输出格式】
    对于每种长度,输出一行,表示答案。

    考试的时候先打了30分的暴力,然后看了几组大数据,发现当边长很大时全部都是0,然后又在保证30分的情况下,牺牲部分正确性换取时间,如果广搜时深度达大于1000层就不往下更新了,然而并没有什么用...最后还是30分...

    30分做法:O(n)枚举起点 对于每一个起点跑一个BFS,搜索同时记录深度、当前路径深度(可以开3个队列),对于每一个深度更新答案(取最大值)

    满分做法:“这种题目一看就是要枚举gcd的!”——By bztMinamoto

          枚举边的gcd值(x),每次把是x的倍数的边加入新图,构成一个森林,然后把里面的树里面的最长链(直径)作为长度更新答案(题目里面的图的下标是边的权值,便于遍历边的时候最快找到)

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 inline int read(){
     7     char chr=getchar();    int f=1,ans=0;
     8     while(!isdigit(chr)) {if(chr=='-') f=-1;chr=getchar();}
     9     while(isdigit(chr))  {ans=(ans<<3)+(ans<<1);ans+=chr-'0';chr=getchar();}
    10     return ans*f;
    11 }
    12 void write(int x){
    13     if(x<0) putchar('-'),x=-x;
    14     if(x>9) write(x/10);
    15     putchar(x%10+'0');
    16 }
    17 const int N=4e5+5;
    18 struct node{int x,y,nxt;}e[N],edge[N<<1];
    19 int st[N],sta[N<<2],tt=0,tot=0;
    20 int p[N<<1],num=0;
    21 int ans[N],mxlen,mx,n,link[N<<1];
    22 inline void Add(int u,int w,int z){e[++tt]={u,w,sta[z]};sta[z]=tt;}//建立原图 
    23 inline void add(int u,int w){edge[++tot]={u,w,st[u]};st[u]=tot;link[tot]=u;edge[++tot]={w,u,st[w]};st[w]=tot;link[tot]=w;}//新图 
    24 int dfs(int now){//求树的直径,不讲...
    25     p[now]=num;
    26     int son=0;
    27     for(int i=st[now];i;i=edge[i].nxt){
    28         if(p[edge[i].y]==num) continue;
    29         int r=dfs(edge[i].y);
    30         mxlen=max(mxlen,r+son+1);
    31         son=max(son,r+1);
    32     }return son;
    33 }
    34 int main(){
    35     freopen("walk.in","r",stdin);
    36     freopen("walk.out","w",stdout);
    37     n=read();
    38     for(int i=1;i<n;i++){
    39         int u=read(),w=read(),z=read();
    40         mx=max(mx,z);Add(u,w,z);
    41     }
    42     for(int i=1;i<=mx;i++){//枚举gcd 
    43         for(int j=i;j<=mx;j+=i)
    44             for(int k=sta[j];k;k=e[k].nxt)add(e[k].x,e[k].y);//建新图 
    45         mxlen=0,num++;
    46         for(int k=1;k<=tot;k++)
    47             if(p[link[k]]!=num) dfs(link[k]);//求直径 
    48         for(int k=1;k<=tot;k++) st[link[k]]=0;
    49         tot=0;ans[mxlen]=i;//更新答案 
    50     }
    51     for(int i=n-1;i>0;i--) ans[i]=max(ans[i],ans[i+1]);
    52     for(int i=1;i<=n;i++)printf("%d
    ",ans[i]);
    53     return 0;
    54 }
  • 相关阅读:
    使用RestTemplate上传文件到远程接口
    设计模式(五)之适配器模式
    设计模式(四)之装饰者模式
    设计模式(三)之模板方法模式
    设计模式(二)之责任链模式
    BUG-jQuery提交表单submit方法-TypeError: e[h] is not a function
    数据类型--集合 set
    数据类型--字典 dic
    字符 str 串需要记住的语法
    数据类型--列表 list
  • 原文地址:https://www.cnblogs.com/zhenglw/p/10333740.html
Copyright © 2011-2022 走看看