Scx117
只一眼,便辽阔了时间。

T1 组合数问题:

用k个不完全相同的组合数表示一个数n。

用k-1个1和一个n-k+1表示即可。

 1 #include<cstdio>
 2 using namespace std;
 3 int x,k;
 4 int main()
 5 {
 6     scanf("%d%d",&x,&k);
 7     for (int i=1;i<k;i++) printf("%d %d\n",i,0);
 8     printf("%d %d\n",x-k+1,1);
 9     return 0;
10 } 

 

T2 喵呜:

问从第x棵树的y高度,跳到第1棵或第n棵树的1或h高度,最少跳跃次数。

跳跃有两种:往左或往右跳a棵树,每次可以往上跳b高度,或往下跳b高度。不能出界。

如果可以跳出界,那么之后一定会跳回正常范围。所以可以证明在跳跃次数一定时必然可构造出不出界的方案。

然后对于四种方案讨论一下:设跳跃距离=k*a,跳跃高度差=g*b。当k>g时,设x为向上跳的次数,x-(g-x)=k,所以x=(k+g)/2,所以只要(k+g)%2=0,x就有整数解。

该方案的最小跳跃次数取max(k,g)。

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 typedef long long ll;
 5 const ll inf=1ll<<60;
 6 ll read()
 7 {
 8     ll x=0;char ch=getchar();
 9     while (ch<'0'||ch>'9') ch=getchar();
10     while ('0'<=ch&&ch<='9') x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
11     return x;
12 }
13 ll n,h,x,y,a,b,Min;
14 void solve(ll k,ll g)
15 {
16     if ((k+g)%2==0) Min=min(Min,max(k,g));
17 }
18 int main()
19 {
20     int T=read();
21     while (T--)
22     {
23         n=read();h=read();x=read();y=read();a=read();b=read();
24         if (abs(x-1)%a!=0&&abs(x-n)%a!=0||abs(y-1)%b!=0&&abs(y-h)%b!=0) {puts("-1");continue;}
25         Min=inf;
26         if (abs(x-1)%a==0&&abs(y-1)%b==0) solve(abs(x-1)/a,abs(y-1)/b);
27         if (abs(x-1)%a==0&&abs(y-h)%b==0) solve(abs(x-1)/a,abs(y-h)/b);
28         if (abs(x-n)%a==0&&abs(y-1)%b==0) solve(abs(x-n)/a,abs(y-1)/b);
29         if (abs(x-n)%a==0&&abs(y-h)%b==0) solve(abs(x-n)/a,abs(y-h)/b);
30         if (Min==inf) puts("-1");else printf("%lld\n",Min);
31     }
32     return 0;
33 }

注意&&不要手滑写成||。

 

T3 白金元首与七彩魔法:

给你一个色盘,求两个点之间的一条线段上的所有点最大的亮度值(计算方式略)。

计算一下线段的斜率,然后用微分的思想算出顶点在线段上的直角三角形的斜边长和tan。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cmath>
 4 using namespace std;
 5 const double pi=acos(-1);
 6 int T,a[3],r[3];
 7 double Max,k,b,x[3],y[3];
 8 double calc(double r,double g,double b)
 9 {return 0.3*r+0.59*g+0.11*b;}
10 double solve(double a,double r)
11 {
12     if (a<0) a+=360;
13     int h=a/60;
14     double f=a/60.0-h,p=1-r,q=1-f*r,t=1-(1-f)*r;
15     if (h==0) t=calc(1,t,p);
16     if (h==1) t=calc(q,1,p);
17     if (h==2) t=calc(p,1,t);
18     if (h==3) t=calc(p,q,1);
19     if (h==4) t=calc(t,p,1);
20     if (h==5) t=calc(1,p,q);
21     return t;
22 }
23 int main()
24 {
25    scanf("%d",&T);
26    while (T--)
27    {
28          scanf("%d%d%d%d",&a[1],&r[1],&a[2],&r[2]);
29          for (int i=1;i<=2;i++)
30          {
31                double g=a[i]/180.0*pi;//math库中的三角函数参数是弧度制
32               x[i]=cos(g)*r[i]/100.0;
33               y[i]=sin(g)*r[i]/100.0;
34           }
35           x[2]-=x[1];y[2]-=y[1];Max=0;
36           for (int i=0;i<=100000;i++)//切割
37           { 
38              double X=x[1]+(double)i/100000.0*x[2];
39              double Y=y[1]+(double)i/100000.0*y[2];
40              Max=max(Max,solve(atan2(Y,X)/pi*180,sqrt(X*X+Y*Y)));
41           }
42          printf("%.4lf\n",Max);
43    }
44    return 0;    
45 } 

注意不要把double开成int。

 

T4 组合数问题2:

求k个组合数的最大和,选取的每个组合数参数<=n且不完全相同。对1e9+7取模。

用一个大根堆维护组合数的大小。类似bfs从第n层中间那个往上方两个和左右扩展。

利用组合数的单调性还可以优化。

特技:用lgammal(x+1)-lgammal(y+1)-lgammal(x-y+1)可以比较出组合数的大小,避免卡精度。(这个东西好像是处理阶乘的log)

 1 #include<bits/stdc++.h> 
 2 using namespace std;
 3 typedef long long ll;
 4 const int mod=1e9+7;
 5 const int N=1000005;
 6 struct node{
 7     double x,y;
 8     node(double A,double B) {x=A;y=B;}
 9 };
10 double calc(node A)
11 {return lgammal(A.x+1)-lgammal(A.y+1)-lgammal(A.x-A.y+1);}
12 struct cmp{
13     bool operator () (const node &A,const node &B)
14     {return calc(A)<calc(B);}
15 };
16 priority_queue<node,vector<node>,cmp> p;
17 int n,k,ans,jc[N],inv[N];
18 map<int,int> mp[N];
19 void init()
20 {
21     jc[0]=jc[1]=inv[0]=inv[1]=1;
22     for (int i=2;i<=n;i++) jc[i]=(ll)jc[i-1]*i%mod,inv[i]=(ll)(mod-mod/i)*inv[mod%i]%mod;
23     for (int i=2;i<=n;i++) inv[i]=(ll)inv[i-1]*inv[i]%mod;
24 }
25 int c(int n,int m) {return (ll)jc[n]*inv[m]%mod*inv[n-m]%mod;}
26 int main()
27 {
28     scanf("%d%d",&n,&k);init();
29     p.push(node(n,n/2));mp[n][n/2]=1;
30     for (int i=1;i<=k;i++)
31     {
32         node now=p.top();p.pop();int x=now.x,y=now.y;
33         int v=c(x,y);
34         ans=((ll)ans+v)%mod;
35         if (x>=1&&x-1>=y&&!mp[x-1][y]) p.push(node(x-1,y)),mp[x-1][y]=1;//注意边界限制!
36         if (x>=1&&y>=1&&!mp[x-1][y-1]) p.push(node(x-1,y-1)),mp[x-1][y-1]=1;
37         if (y>=1&&!mp[x][y-1]) p.push(node(x,y-1)),mp[x][y-1]=1;
38         if (y+1<=x&&!mp[x][y+1]) p.push(node(x,y+1)),mp[x][y+1]=1;
39     }
40     printf("%d\n",ans);
41     return 0;
42 }

注意不要把取了模的东西扔进堆里比较。

 

posted on 2018-04-02 10:00  Scx117  阅读(206)  评论(0编辑  收藏  举报