BYRBT

Codeforces 340

A:

询问[l,r]之间有多少个能被x整除的数。

这是简要的题意,分类居然是math。

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 
 5 using namespace std;
 6 
 7 int gcd(int a,int b)
 8 {
 9     if (!b) return a;
10     else return gcd(b,a%b);
11 }
12 
13 int main()
14 {
15     int x,y,a,b;
16     scanf("%d%d%d%d",&x,&y,&a,&b);
17     x=x/gcd(x,y)*y;
18     printf("%d\n",b/x-(a-1)/x);
19 
20     return 0;
21 }
View Code

 

B:

询问面积最大的四边形。

枚举对角线,两边用叉积找左边和右边最大的三角形。

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<algorithm>
 5 
 6 using namespace std;
 7 
 8 const int maxn=310;
 9 const int INF=0x3f3f3f3f;
10 
11 int n,x[maxn],y[maxn];
12 
13 int cross(int a,int b,int c)
14 {
15     return (x[c]-x[b])*(y[b]-y[a])-(x[b]-x[a])*(y[c]-y[b]);
16 }
17 
18 int main()
19 {
20     scanf("%d",&n);
21     for (int a=1;a<=n;a++)
22         scanf("%d%d",&x[a],&y[a]);
23     int ans=0;
24     for (int a=1;a<=n;a++)
25         for (int b=a+1;b<=n;b++)
26         {
27             int maxv=-INF,minv=INF;
28             for (int c=1;c<=n;c++)
29                 if (c!=a && c!=b)
30                 {
31                     int v=cross(a,b,c);
32                     maxv=max(maxv,v);
33                     minv=min(minv,v);
34                 }
35             if (minv<=0 && maxv>=0) ans=max(ans,maxv-minv);
36         }
37     printf("%lf\n",(double)ans/2.0);
38 
39     return 0;
40 }
View Code

 

C:

这一场里面最悲哀的是我居然没能顺利的想出这题……唉……

给n个点,每个点需访问一次,问期望走的总长度。

算出每段之间的会被走多少次除以总可能性就行呢,中途可以发现大部分会被直接约掉。

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<algorithm>
 5 
 6 using namespace std;
 7 
 8 const int maxn=100010;
 9 
10 int n,z[maxn];
11 
12 long long gcd(long long a,long long b)
13 {
14     if (!b) return a;
15     else return gcd(b,a%b);
16 }
17 
18 int main()
19 {
20     scanf("%d",&n);
21     for (int a=1;a<=n;a++)
22         scanf("%d",&z[a]);
23     sort(z+1,z+n+1);
24     long long ans=(long long)n*z[1];
25     for (int a=1;a<n;a++)
26         ans+=((long long)a*(n-a)*2+(n-a))*(z[a+1]-z[a]);
27     long long x=n;
28     long long g=gcd(ans,x);
29     printf("%I64d %I64d\n",ans/g,x/g);
30 
31     return 0;
32 }
View Code

 

D:

题意简化之后就是逆序对之间建立边然后求最大独立集。

那么就是要求一个没有逆序对的最长序列,就是最长上升子序列了。

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<algorithm>
 5 
 6 using namespace std;
 7 
 8 #define lb(x) ((x)&(-(x)))
 9 
10 const int maxn=100010;
11 
12 int n,z[maxn];
13 
14 int query(int p)
15 {
16     int ans=0;
17     for (;p;p-=lb(p))
18         ans=max(ans,z[p]);
19     return ans;
20 }
21 
22 void modify(int p,int v)
23 {
24     for (;p<=n;p+=lb(p))
25         z[p]=max(z[p],v);
26 }
27 
28 int main()
29 {
30     scanf("%d",&n);
31     for (int a=1;a<=n;a++)
32     {
33         int v;
34         scanf("%d",&v);
35         modify(v,query(v)+1);
36     }
37     printf("%d\n",query(n));
38 
39     return 0;
40 }
View Code

 

E:

n个数,有些位置是-1,将-1的位置填上数,使得变为一个1-n的排列,且任意ai都不等于i,问方案数。

首先用一个dp做出n个点不存在长度为1的环的方案数,HZC说这是斯特灵数,我只能表示不明觉厉。大概是f[i][j]表示有i个点已加入且有j个长度为1的环,转移就考虑是新增环还是消环即可。

然后再做一次DP,f[i][j]表示已经填了i个数还有j个可能出现重复位置的数,如果剩下的数和j相等了就直接调用上一次做的DP的值,否则考虑选数是选哪一种数即可。

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 
 5 using namespace std;
 6 
 7 #define inc(a,b) {a+=b;if (a>=mo) a-=mo;}
 8 
 9 const int maxn=2010;
10 const int mo=1000000007;
11 
12 int n,f[maxn][maxn],g[maxn][maxn],h[maxn];
13 
14 bool placelose[maxn],show[maxn];
15 
16 int main()
17 {
18     scanf("%d",&n);
19     int cnt1=0,cnt2=0;
20     for (int a=1;a<=n;a++)
21     {
22         int v;
23         scanf("%d",&v);
24         if (v==-1) placelose[a]=true,cnt1++;
25         show[v]=true;
26     }
27     for (int a=1;a<=n;a++)
28         if (!show[a] && placelose[a]) cnt2++;
29     g[0][0]=1;
30     for (int a=0;a<cnt2;a++)
31         for (int b=0;b<=cnt2;b++)
32             if (g[a][b])
33             {
34                 inc(g[a+1][b+1],g[a][b]);
35                 inc(g[a+1][b],(long long)g[a][b]*(a-b)%mo);
36                 if (b) inc(g[a+1][b-1],(long long)g[a][b]*b%mo);
37             }
38     for (int a=1;a<=cnt2;a++)
39         h[a]=g[a][0];
40     f[0][cnt2]=1;
41     int ans=0;
42     for (int a=0;a<cnt1;a++)
43         for (int b=0;b<=cnt2;b++)
44             if (f[a][b])
45             {
46                 if (cnt1-a==b) inc(ans,(long long)h[b]%mo*f[a][b]%mo)
47                 else
48                 {
49                     inc(f[a+1][b],(long long)f[a][b]*(cnt1-a-b)%mo);
50                     inc(f[a+1][b-1],(long long)f[a][b]*b%mo);
51                 }
52             }
53     printf("%d\n",(ans+f[cnt1][0])%mo);
54 
55     return 0;
56 }
View Code

 

 

posted @ 2013-08-31 22:29  zhonghaoxi  阅读(308)  评论(0编辑  收藏  举报
BYRBT