Codeforces Round #382 (Div. 2) 解题报告

  CF一如既往在深夜举行,我也一如既往在周三上午的C++课上进行了virtual participation。这次div2的题目除了E题都水的一塌糊涂,参赛时的E题最后也没有几个参赛者AC,排名又成为了手速与精准的竞争……(遗憾,如果参加了一定可以上分的吧orz)

  A题:

  先判断起点和终点的距离是否被每次跳的距离整除,如果不整除就到不了。再检验跳跃过程中的落点是否均合法即可。

  

 1 #include<stdio.h>
 2 #include<bits/stdc++.h>
 3 #include <iostream>
 4 using namespace std;
 5 typedef long long ll;
 6 int k,n;
 7 char a[200];
 8 void solve(int st,int en)
 9 {
10     if((en-st)%k!=0)
11     {
12         printf("NO\n");
13         return ;
14     }
15     int j;
16     for(j=st+k;j<en;j+=k)
17     {
18         if(a[j]=='#')
19         {
20             printf("NO\n");
21             return;
22         }
23     }
24 //    if(j<en)
25         printf("YES\n");
26 
27 }
28 int main()
29 {
30     int i,si,ei;
31     scanf("%d%d",&n,&k);
32     scanf("%s",a);
33     for(i=0;i<n;i++)
34     {
35         if(a[i]=='G')
36             ei=i;
37         if(a[i]=='T')
38             si=i;
39     }
40     if(ei<si)
41         swap(ei,si);
42     solve(si,ei);
43     return 0;
44 }

  B题:

  根据题意,只需要想清楚最佳分配方案。根据排序不等式,即可轻松找到最佳方案。将人排序后,让从大到小的前若干个人分到人数小的城市,接下来再若干人分到人数多的城市即可得到最大值。

  

 1 #include<stdio.h>
 2 #include<bits/stdc++.h>
 3 #include <iostream>
 4 using namespace std;
 5 typedef long long ll;
 6 ll n,a[2],ren[100005],i,he1=0,he2=0;
 7 double an=0;
 8 int main()
 9 {
10 
11     scanf("%I64d%I64d%I64d",&n,&a[0],&a[1]);
12     if(a[0]>a[1])
13         swap(a[0],a[1]);
14     for(i=0;i<n;i++)
15         scanf("%I64d",&ren[i]);
16     sort(ren,ren+n);
17 for(i=n-1;i>=n-a[0];i--)
18 {
19     he1+=ren[i];
20 }
21 for(i=n-a[0]-1;i>=n-a[0]-a[1];i--)
22 {
23     he2+=ren[i];
24 }
25 an=(1.0*he1/a[0])+(1.0*he2/a[1]);
26 printf("%.8f\n",an);
27     return 0;
28 }

  C题:

  观察比赛场次和人数的关系,以及比赛场次何时+1即可发现这题本质上是斐波那契数列。设人x时开始变为最多比赛q场,人y时开始变为最多比赛q+1场,则人(x+y)时,前x个人可以找到比赛q场的唯一到最后的选手,后y个人可以找到比赛(q+1)场后唯一到最后的选手,这两个人可以比赛,并且会得出胜者,如果后y人中的胜者获得胜利,就构造出了最多参加(q+2)场的情况。并且可以归纳证明这是最少的人数。于是就证明了本题斐波那契数列的本质。

  

 1 #include<stdio.h>
 2 #include<bits/stdc++.h>
 3 #include <iostream>
 4 using namespace std;
 5 typedef long long ll;
 6 ll n;
 7 ll fi(ll x)
 8 {
 9     if(x==2)
10         return 1;
11     if(x==3)
12         return 2;
13     else
14 
15     {
16         ll x1,x2,tem,cnt;
17         cnt=2;x1=3;x2=2;
18         while(x1<x)
19         {
20             tem=x1;
21             x1=x1+x2;
22             x2=tem;
23             cnt++;
24         }
25         if(x1==x)
26             return cnt;
27         else
28             return cnt-1;
29     }
30 }
31 int main()
32 {
33     scanf("%I64d",&n);
34     printf("%I64d\n",fi(n));
35     return 0;
36 }

  D题:

  乍一看和素数相关,数还特别大,比较吓人。而实际上利用哥德巴赫猜想的内容即可轻松解决(虽然还没有证明为真,但这样数量级的数之前都已经用计算机验证过了)

  注意到:任何一个大于2的偶数都是两个素数之和。那么对于输入的如果是偶数,2就输出1(因为本身是质数),其余就输出2(根据猜想,可以分为两个质数之和)

      任何大于5的奇数都是三个素数之和。那么对于输入的如果是奇数,判断是否为质数(这里我比较懒,直接用了拉宾米勒,实际上简单的从2到根号n循环一遍就可以),是就输出1,不是的话再看(n-2)是否为质数,如果是,就可以将其分为2和(n-2)这样两个质数,那么就输出2。不然就只能根据猜想,一定可以分为3个质数,输出3。

  

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<stdlib.h>
  4 #include<time.h>
  5 #include<iostream>
  6 #include<string.h>
  7 #include<math.h>
  8 #include<algorithm>
  9 using namespace std;
 10 
 11 //****************************************************************
 12 // Miller_Rabin 算法进行素数测试
 13 //速度快,而且可以判断 <2^63的数
 14 //****************************************************************
 15 const int S=20;//随机算法判定次数,S越大,判错概率越小
 16 
 17 
 18 //计算 (a*b)%c.   a,b都是long long的数,直接相乘可能溢出的
 19 //  a,b,c <2^63
 20 long long mult_mod(long long a,long long b,long long c)
 21 {
 22     a%=c;
 23     b%=c;
 24     long long ret=0;
 25     while(b)
 26     {
 27         if(b&1){ret+=a;ret%=c;}
 28         a<<=1;
 29         if(a>=c)a%=c;
 30         b>>=1;
 31     }
 32     return ret;
 33 }
 34 
 35 
 36 
 37 //计算  x^n %c
 38 long long pow_mod(long long x,long long n,long long mod)//x^n%c
 39 {
 40     if(n==1)return x%mod;
 41     x%=mod;
 42     long long tmp=x;
 43     long long ret=1;
 44     while(n)
 45     {
 46         if(n&1) ret=mult_mod(ret,tmp,mod);
 47         tmp=mult_mod(tmp,tmp,mod);
 48         n>>=1;
 49     }
 50     return ret;
 51 }
 52 
 53 
 54 
 55 
 56 
 57 //以a为基,n-1=x*2^t      a^(n-1)=1(mod n)  验证n是不是合数
 58 //一定是合数返回true,不一定返回false
 59 bool check(long long a,long long n,long long x,long long t)
 60 {
 61     long long ret=pow_mod(a,x,n);
 62     long long last=ret;
 63     for(int i=1;i<=t;i++)
 64     {
 65         ret=mult_mod(ret,ret,n);
 66         if(ret==1&&last!=1&&last!=n-1) return true;//合数
 67         last=ret;
 68     }
 69     if(ret!=1) return true;
 70     return false;
 71 }
 72 
 73 // Miller_Rabin()算法素数判定
 74 //是素数返回true.(可能是伪素数,但概率极小)
 75 //合数返回false;
 76 
 77 bool Miller_Rabin(long long n)
 78 {
 79     if(n<2)return false;
 80     if(n==2)return true;
 81     if((n&1)==0) return false;//偶数
 82     long long x=n-1;
 83     long long t=0;
 84     while((x&1)==0){x>>=1;t++;}
 85     for(int i=0;i<S;i++)
 86     {
 87         long long a=rand()%(n-1)+1;//rand()需要stdlib.h头文件
 88         if(check(a,n,x,t))
 89             return false;//合数
 90     }
 91     return true;
 92 }
 93 typedef long long ll;
 94 ll n;
 95 int main()
 96 {
 97     scanf("%I64d",&n);
 98     if(n==2)
 99     {printf("1\n");return 0;}
100     if(n%2==0)
101         printf("2\n");
102     else
103     {
104         if(Miller_Rabin(n))
105             {
106                 printf("1\n");
107 
108             }
109         else
110             {
111                 if(Miller_Rabin(n-2))
112                     printf("2\n");
113                 else
114                     printf("3\n");
115             }
116 
117     }
118     return 0;
119 }

  E题好难,貌似还得用到树状dp,还没有学到orz,等以后再回来填坑。(捂脸,估计看解题报告的大家其实想看的就是E题吧……)

posted @ 2016-11-30 10:54  perplex  阅读(290)  评论(0编辑  收藏  举报