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

C:Half and Half

几个if语句贪心算一算就好了

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 int a,b,c,x,y,t;
 5 int main()
 6 {
 7     scanf_s("%d%d%d%d%d",&a,&b,&c,&x,&y);c*=2;
 8     a=min(a,c);b=min(b,c);
 9     if (a+b<=c) printf("%d\n",x*a+y*b);
10     else t=min(x,y),printf("%d\n",t*c+(x-t)*a+(y-t)*b);
11     return 0;
12 } 

 

D:Static Sushi

这是个环形吧台,所以可以正着走、倒着走、正着走再倒着走、倒着走再正着走。

记录一个前缀和即可。

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 typedef long long ll;
 5 const int N=100005;
 6 int n,pos1,pos2; 
 7 ll C,x[N],w[N],sum,Max,Max1[N],Max2[N];
 8 int main()
 9 {
10     scanf("%d%lld",&n,&C);
11     for (int i=1;i<=n;i++) scanf("%lld%lld",&x[i],&w[i]);
12     for (int i=1;i<=n;i++) 
13       sum+=w[i],Max1[i]=max(Max1[i-1],sum-x[i]);
14     sum=0;
15     for (int i=n;i>=1;i--) 
16        sum+=w[i],Max2[i]=max(Max2[i+1],sum-(C-x[i]));
17     Max=max(Max1[n],Max2[1]);
18     sum=0;
19     for (int i=1;i<=n;i++) sum+=w[i],Max=max(Max,Max2[i+1]+sum-x[i]*2); 
20     sum=0;
21     for (int i=n;i>=1;i--) sum+=w[i],Max=max(Max,Max1[i-1]+sum-(C-x[i])*2);
22     printf("%lld\n",Max);
23     return 0;
24 }

 

晚了五分钟开,名次掉飞真是不开心。。。

 

E:Everything on it

可以选择任意碗拉面,每碗的配料组合必须不同。配料一共有$n$种,$2^n$种组合。问有多少种选拉面的方案可以使得每一种配料都至少出现了两次?$n<=3000$。

容斥。设f[i]为至少有i种配料出现次数<=1的方案数。那么$ans=\sum_{i=0}^{n}((-1)^i*f[i]*C(n,i))$。

怎么求f[i]?比较麻烦的地方是一个数中有多个配料,怎么来保证选取的i个配料必然出现<=1次?

考虑第二类斯特灵数的前缀和s[i][j]表示<=i个元素分到非空的j的集合的方案数。

即i种配料要么不出现,要么被分到集合中,同一个集合的出现在同一个二进制数里,有$2^ {n-i}$种方案(其他n-i种随意,这一个集合中的同时出现)。有j个集合,不同集合之间独立,就有$(2^{n-i})^j$种方案。其余n-i种配料的组合任意,因此$f[i]=\sum_{j=0}^{i}s[i][j]*2^{(n-i)*j}*2^{2^{n-i}}$。

 1 #include<cstdio>
 2 using namespace std;
 3 typedef long long ll;
 4 const int N=3005;
 5 int ans,n,mod,jc[N],inv[N],s[N][N],f[N],pw[N*N];
 6 int ksm(int x,int y,int mod)
 7 {
 8   int res=1;
 9   while (y) {if (y&1) res=(ll)res*x%mod;x=(ll)x*x%mod;y>>=1;}
10   return res;
11 }
12 int c(int n,int m) {return (ll)jc[n]*inv[m]%mod*inv[n-m]%mod;}
13 int main()
14 {
15     scanf("%d%d",&n,&mod);
16     jc[0]=jc[1]=inv[0]=inv[1]=pw[0]=1;
17     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;
18     for (int i=2;i<=n;i++) inv[i]=(ll)inv[i-1]*inv[i]%mod;
19     for (int i=1;i<=n*n;i++) pw[i]=(ll)pw[i-1]*2%mod;
20     for (int i=0;i<=n;i++) s[i][0]=1;//初始化,都有一种可能分到0个集合 
21     for (int i=1;i<=n;i++)
22       for (int j=1;j<=i;j++)
23         s[i][j]=((ll)s[i-1][j-1]+(ll)(j+1)*s[i-1][j]%mod)%mod;//<=i个元素分入j个非空集合的方案数  
24     for (int i=0;i<=n;i++)
25     {
26        for (int j=0;j<=i;j++) f[i]=((ll)f[i]+(ll)s[i][j]*pw[(n-i)*j]%mod)%mod;
27        f[i]=(ll)f[i]*ksm(2,ksm(2,n-i,mod-1),mod)%mod;    
28     }
29     for (int i=0;i<=n;i++)
30       if (i&1) ans=((ll)ans-(ll)c(n,i)*f[i]%mod+mod)%mod;
31       else ans=((ll)ans+(ll)c(n,i)*f[i]%mod)%mod;
32     printf("%d\n",ans);
33     return 0;
34 }

 

F:不会,待填坑

posted on 2018-04-22 11:12  Scx117  阅读(376)  评论(0编辑  收藏  举报