zoukankan      html  css  js  c++  java
  • 【qboi冲刺NOIP2017复赛试题4】 全套题目+题解+程序

    作为一个好人(验题人),我给大家奉上下这套题的题解,并且预祝大家这套题能够AK:

    T1题面:Alice现在有n根木棍,他们长度为1,2,3....n,Bob想把某一些木棍去掉,使得Alice剩下的木棍任意3根不能构成三角形。Bob想知道至少他需要去掉多少根。

    题解:不难发现,这一题所求为在[1,n]中有多少个数不是斐波那契数,因为n的范围很小,直接枚举即可。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #define L long long
     5 using namespace std;
     6 L n,a=1,b=2,c;
     7 
     8 int main(){
     9     freopen("a.in","r",stdin);
    10     freopen("a.out","w",stdout);
    11     cin>>n;
    12     if(n<=3) {printf("0
    "); return 0;}
    13     int i;
    14     for(i=2;a+b<=n;i++){
    15         c=a+b;
    16         a=b; b=c;
    17     }
    18     cout<<n-i<<endl;
    19 }

    第二题题面:给你n堆石子,每堆石子有ai个石子,对于每一次操作,可以将某堆的一个石子移动到另外一堆。游戏终止的条件是:存在一个x(x>1),使得任意一堆石子满足:ai%x==0。(1<=i<=n)请求出游戏终止的最小操作数。

    我们不难发现,x必为sum的因子,枚举所有的因子d,对于该因子d,将a数组中每一个数取模并排序,最后贪心地扫一遍即可。

    时间复杂度为$O(n*d(sum^{0.5}))$

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define M 110000
     6 #define L long long
     7 using namespace std;
     8 int a[M]={0},b[M]={0},dd[M]={0},n,dn;
     9 L ans=0,minn=1e18;
    10 
    11 void sort(int x){
    12     for(int i=1;i<=n;i++) dd[b[i]]++;
    13     int cnt=0;
    14     for(int i=0;i<x;i++){
    15         while(dd[i]) b[++cnt]=i,dd[i]--;
    16     }
    17 }
    18 
    19 int main(){
    20     cin>>n;
    21     for(int i=1;i<=n;i++) scanf("%d",a+i),ans+=a[i];
    22     for(int d=2;d<=100000;d++) if(ans%d==0){
    23         L sum=0,cnt=0;
    24         for(int i=1;i<=n;i++) b[i]=a[i]%d;
    25         sort(d);
    26         //sort(b+1,b+n+1);
    27         for(int i=1,j=n;i<j;i++){
    28             while(b[i]){
    29                 int delta=min(b[i],d-b[j]);
    30                 cnt+=delta;
    31                 b[j]+=delta;
    32                 b[i]-=delta;
    33                 if(b[j]==d) j--;//!!!
    34             }
    35         }
    36         minn=min(minn,cnt);
    37     }
    38     cout<<minn<<endl;
    39 }
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define M 110000
     6 #define L long long
     7 using namespace std;
     8 int a[M]={0},b[M]={0},dd[M]={0},n,dn;
     9 L ans=0,minn=1e18;
    10 
    11 void sort(int x){
    12     for(int i=1;i<=n;i++) dd[b[i]]++;
    13     int cnt=0;
    14     for(int i=0;i<x;i++){
    15         while(dd[i]) b[++cnt]=i,dd[i]--;
    16     }
    17 }
    18 
    19 int main(){
    20     cin>>n;
    21     for(int i=1;i<=n;i++) scanf("%d",a+i),ans+=a[i];
    22     for(int d=2;d<=100000;d++) if(ans%d==0){
    23         L sum=0,cnt=0;
    24         for(int i=1;i<=n;i++) b[i]=a[i]%d;
    25         sort(d);
    26         //sort(b+1,b+n+1);
    27         for(int i=1,j=n;i<j;i++){
    28             while(b[i]){
    29                 int delta=min(b[i],d-b[j]);
    30                 cnt+=delta;
    31                 b[j]+=delta;
    32                 b[i]-=delta;
    33                 if(b[j]==d) j--;//!!!
    34             }
    35         }
    36         minn=min(minn,cnt);
    37     }
    38     cout<<minn<<endl;
    39 }

    第三题题解:简单乱搞题,直接暴力枚举即可。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #define M 1100
     5 using namespace std;
     6 int n,m,d;
     7 struct pt{
     8     int x,y; pt(){x=y=0;}
     9     pt(int xx,int yy) {x=xx; y=yy;}
    10 }a[M];
    11 int f[M]={0},ok[M]={0};
    12 int get(int x){
    13     if(f[x]!=x) return f[x]=get(f[x]);
    14     return x;
    15 }
    16 int pf(int x){return x*x;}
    17 bool cmp(int x,int y){
    18     return pf(a[x].x-a[y].x)+pf(a[x].y-a[y].y)<=d*d;
    19 }
    20 struct edge{int u,next;}e[M*M]={0}; int head[M]={0},use=0;
    21 void add(int x,int y){use++;e[use].u=y;e[use].next=head[x]; head[x]=use;}
    22 int main(){
    23     scanf("%d%d%d",&n,&m,&d);
    24     for(int i=1;i<=n;i++) scanf("%d%d",&a[i].x,&a[i].y);
    25     for(int i=1;i<=n;i++){
    26         for(int j=1;j<=n;j++) if(i!=j)
    27         if(cmp(i,j)) 
    28         add(i,j);
    29     }
    30     for(int i=1;i<=n;i++) f[i]=i;
    31     while(m--){
    32         char c[10]; int x,y; 
    33         scanf("%s%d",&c,&x);
    34         if(c[0]=='O'){
    35             ok[x]=1;
    36             for(int i=head[x];i;i=e[i].next) if(ok[e[i].u]){
    37                 int xx=get(x),yy=get(e[i].u);
    38                 if(xx==yy) continue;
    39                 f[xx]=yy;
    40             }
    41         } else{
    42             scanf("%d",&y);
    43             x=get(x); y=get(y);
    44             if(x==y) printf("YES
    ");
    45             else printf("NO
    ");
    46         }
    47     }
    48 }

    第四题题解:我们对所所有的买卖方案按 Q-P 的大小 ,从小到大排序,然后直接跑01背包即可。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 struct node
     4 {
     5     int p,q,v;
     6     node(){}
     7     bool operator < (const node &a) const
     8     {
     9         return q-p < a.q - a.p;
    10     }
    11     void read() {scanf("%d%d%d",&p,&q,&v);}
    12 }a[1000];
    13 int f[100050];
    14 int main()
    15 {
    16     int n,m;
    17     while (scanf("%d%d",&n,&m)!=EOF)
    18     {
    19         memset(f,0,sizeof(f));
    20         for (int i=1; i<=n; i++) a[i].read();
    21         sort(a+1,a+1+n);
    22         for (int i=1; i<=n; i++)
    23             for (int j=m; j>=a[i].q; j--)
    24                 f[j] = max(f[j], f[j-a[i].p]+a[i].v);
    25         printf("%d
    ",f[m]);
    26     }
    27 }

    是不是很简单啊??

  • 相关阅读:
    L1-050 倒数第N个字符串 (15分)
    Oracle存储过程的疑难问题
    Linux的细节
    Linux字符设备和块设备的区别
    Shell变量
    游标的常用属性
    Oracle中Execute Immediate用法
    Oracle中的sqlerrm和sqlcode
    Oracle把一个表的数据复制到另一个表中
    Oracle的差异增量和累积增量
  • 原文地址:https://www.cnblogs.com/xiefengze1/p/7746424.html
Copyright © 2011-2022 走看看