# Noip simulation 85 2021.10.29 (to depression Trilogy)

Posted by le007 on Fri, 29 Oct 2021 12:32:40 +0200

## preface

Thanks to the author, I was directly depressed in the examination room

Although I only saw Darling in the FRANXX, I still felt bad for \ (ichigo \) for a long time

## T1 \ ((ichigo) \)

I came to see you dressed up like you like, Guang, no, da, darling

Uncomfortable!!! But it's hard for me to cut \ (T1 \) without cutting it off

On the examination room, I saw one film at a time, and I didn't care about the rest. I just called \ (T1 \)

However, it can only be said that this thing is too powerful. For the \ (n \) row of sterling number that has been pushed for a long time by typing + \ (dp \) in the examination room, it can be done two or three times

$$\begin{Bmatrix}n\\k\end{Bmatrix}=\frac{1}{k!}\sum\limits_{i=0}^{k}\binom{k}{i}(k-i)^{n}$$

Explain that there are several empty sets in the enumeration of \ (K \) sets. After selecting these empty sets, the remaining numbers are randomly placed in \ ((k-i) \) non empty sets, multiplied by the inclusion exclusion coefficient, and then randomly arranged \ (k! \)

Then the problem is very simple. It is found that the number of contributions of each magmatic energy is equal, so only consider the number of contributions of the first magmatic energy

It's not hard to find that \ (\ begin{Bmatrix}n\k\end{Bmatrix}+(n-1)\times\begin{Bmatrix}n-1\k\end{Bmatrix} \)

So the answer is \ (ans=\sum w\times(\begin{Bmatrix}n\k\end{Bmatrix}+(n-1)\times\begin{Bmatrix}n-1\k\end{Bmatrix}) \)

ichigo
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int NN=1e6+5,mod=998244353;
namespace AE86{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
};
auto write=[](int x,char opt='\n'){
char ch[20];short len=0;if(x<0)x=~x+1,putchar('-');
do{ch[len++]=x%10+(1<<5)+(1<<4);x/=10;}while(x);
for(short i=len-1;i>=0;--i)putchar(ch[i]);putchar(opt);
};
}using namespace AE86;
int n,k,sm,pw[NN][2],prime[NN],len,h[NN],v[NN];
bool vis[NN];
auto qmo=[](int a,int b,int ans=1){
int c=mod;for(;b;b>>=1,a=a*a%c)if(b&1)ans=ans*a%c;
return ans;
};
auto inv=[](int x){return qmo(x,mod-2);};
auto prework=[](){
pw[1][0]=pw[1][1]=1; h[0]=h[1]=1;
for(int i=2;i<=k;i++){
h[i]=h[i-1]*i%mod;
if(!vis[i]) prime[++len]=i,pw[i][0]=qmo(i,n),pw[i][1]=qmo(i,n-1);
for(int j=1;j<=len&&prime[j]*i<=k;j++){
vis[i*prime[j]]=1;
pw[i*prime[j]][1]=pw[i][1]*pw[prime[j]][1]%mod;
pw[i*prime[j]][0]=pw[i][0]*pw[prime[j]][0]%mod;
if(i%prime[j]==0){
break;
}
}
}
v[k]=inv(h[k]); v[0]=v[1]=1;
for(int i=k-1;i>=2;i--) v[i]=v[i+1]*(i+1)%mod;
};
auto C=[](int n,int m){return (n<m||n<0||m<0)?0:h[n]*v[n-m]%mod*v[m]%mod;};
auto S=[](int opt,int k){
int ans=qmo(h[k],mod-2),tmp=0;
for(int i=0,bs=1;i<=k;i++,bs*=-1)
tmp=(tmp+bs*C(k,i)*pw[k-i][opt]%mod+mod)%mod;
return ans*tmp%mod;
};
namespace WSN{
inline short main(){
freopen("ichigo.in","r",stdin);
freopen("ichigo.out","w",stdout);
int tmp=sm*((S(0,k)+(n-1)*S(1,k)%mod)%mod)%mod;
write(tmp);
return 0;
}
}
signed main(){return WSN::main();}


## T2 done \ ((eriri) \)

Have I become the first in your heart?

All \ (dp \) are coded in the examination room, but the array is not sorted

Because I felt that there was \ (dp \) greed and there was no point in scolding, so I pretended to be dead...

So I found it and replaced it with \ (permutation \)....

Consider that if you buy items in the store \ (i \) at time \ (t \), go to the store \ (j \) immediately after the end

Then \ (J \) will spend \ ((a_i\times t+b_i+1)\times a_j \) extra time waiting at \ (I \)

If we exchange the order of the two and buy them at \ (t \) at \ (j \),

Go to \ (I \) to buy it immediately after it is finished, and \ (I \) will spend an additional \ ((a_j\times t+b_j+1)\times a_i \)

If going first \ (i \) is better than going first \ (j \), it needs to be met

$$(a_i\times t+b_i+1)\times a_j\leq(a_j\times t+b_j+1)\times a_i$$

Namely

$$(b_i+1)\times a_j\leq(b_j+1)\times a_i$$

Then sort according to this. If it is found that \ (a_i=0 \) will be at the end, find them and sort them in ascending order according to \ (b \)

First, do the previous \ (a_i > 0 \) according to \ (dp \)

Setting \ (dp_{i,j} \) means that considering \ (I \) stores, it takes the least time to purchase items from \ (j \) stores

Then the transfer equation is

$$dp_{i,j}=\min(dp_{i-1,j},dp_{i-1,j-1}+1+(dp_{i-1,j-1}+1)\times a_i+b_i)$$

Then take a look at the remaining \ (b \) and choose at most

eriri
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int NN=2e5+5;
namespace AE86{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
};
auto write=[](int x,char opt='\n'){
char ch[20];short len=0;if(x<0)x=~x+1,putchar('-');
do{ch[len++]=x%10+(1<<5)+(1<<4);x/=10;}while(x);
for(short i=len-1;i>=0;--i)putchar(ch[i]);putchar(opt);
};
}using namespace AE86;
int n,T,f[NN][31],cnt,res,lg,ans;
struct node{
int a,b;
friend bool operator<(node x,node y){
return (x.b+1)*y.a<(y.b+1)*x.a;
}
}s[NN];
namespace WSN{
inline short main(){
freopen("eriri.in","r",stdin);
freopen("eriri.out","w",stdout);
for(int i=1;i<=n;i++)
sort(s+1,s+n+1);
for(int i=n;i;i--) if(!s[i].a) ++cnt;
sort(s+n-cnt+1,s+n+1,[](node x,node y)->bool{return x.b<y.b;});
res=n-cnt;
memset(f,0x3f,sizeof(f));
for(int i=0;i<=res;i++) f[i][0]=0;
for(int i=1;i<=res;i++){
for(int j=1;j<=min(i,30ll);j++) f[i][j]=f[i-1][j];
for(int j=1;j<=min(i,30ll);j++){
if(f[i-1][j-1]>1e18) continue;
if(f[i-1][j-1]+1+(f[i-1][j-1]+1)*s[i].a+s[i].b<=T)
f[i][j]=min(f[i][j],f[i-1][j-1]+1+(f[i-1][j-1]+1)*s[i].a+s[i].b);
}
}
for(int i=0;i<=min(res,30ll);i++) if(f[res][i]<=T) ans=max(ans,i);
int sm=0;
for(int i=res+1;i<=n;i++){
sm+=s[i].b+1;
for(int j=1;j<=min(res,30ll);j++)
if(sm+f[res][j]<=T)
ans=max(ans,j+i-res);
}
write(ans);
return 0;
}
}
signed main(){return WSN::main();}


## T3 group \ ((yui) \)

Tears didn't come out. Because I've cried many times.

On the premise of limiting the number of stones in each pile to be different from each other, the number of schemes that must be defeated first is subtracted from the number of schemes

Let \ (p_i=(2^n-1)^{\underline{i} \), that is, the total number of schemes for \ (I \) rockfill

Let \ (f_i \) represent the number of schemes that must be defeated first when filling stones

We consider that the first \ (i-1 \) pile of stones can be taken arbitrarily, and the XOR sum is \ (0 \) by adjusting the number of the last pile of stones,
Number of schemes \ (p#u{i-1} \)

If the exclusive or sum of stones in the previous \ (i-1 \) pile is \ (0 \), because \ (0 \) cannot be taken in the last pile, this situation is illegal
, the number of schemes is \ (f#u{i-1} \)

If the exclusive or of \ (I-2 \) stones in the previous \ (i-1 \) stones is \ (0 \), then the number of stones in the last pile can only be the same as that in the other pile, which is also illegal. The number of schemes is \ ((i-1)\times(2^n-i+1)\times f_{i-2} \)

So we get \ (f_i=p_{i − 1} − f_{i − 1}-(i-1)\times(2^n-i+1)\times f_{i-2} \), and the boundary is
$$f_1=f_2=0$$, direct \ (O(n) \) recursion.

I haven't seen the wrong solution for a long time (crazy death)

yui
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=1e9+7,NN=1e7+5;
namespace AE86{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
};
auto write=[](int x,char opt='\n'){
char ch[20];short len=0;if(x<0)x=~x+1,putchar('-');
do{ch[len++]=x%10+(1<<5)+(1<<4);x/=10;}while(x);
for(short i=len-1;i>=0;--i)putchar(ch[i]);putchar(opt);
};
}using namespace AE86;
int n,tot,f[NN],p[NN];
auto qmo=[](int a,int b,int ans=1){
int c=mod;for(;b;b>>=1,a=a*a%c)if(b&1)ans=ans*a%c;
return ans;
};
auto inv=[](int x){return qmo(x,mod-2);};
auto prework=[](){
p[0]=1; f[1]=f[2]=0; int pw2=qmo(2,n);
for(int i=1;i<=n;i++) p[i]=(pw2-i+mod)%mod*p[i-1]%mod;
for(int i=3;i<=n;i++) f[i]=p[i-1]-f[i-1]-(i-1)*((pw2-i+1+mod)%mod)%mod*f[i-2]%mod;
};
namespace WSN{
inline short main(){
freopen("yui.in","r",stdin);
freopen("yui.out","w",stdout);
write((p[n]-f[n]+mod)%mod);
return 0;
}
}
signed main(){return WSN::main();}


## T4 seven negative self \ ((nanami) \)

Since it's really white, if you don't want it, Mr. Kanda belongs to me.

$$\ textit{meet in the middle}$$, which means to find the largest group

The clique is defined as a complete graph, that is, to find the largest complete subgraph

Then directly enumerate half of the complete subgraphs, and then find the largest complete subgraph through the edge between the two halves

Then divide the working hours equally and calculate the contribution. It is proved to be complex. The adjustment method can be used. However, I am not very good at the adjustment method

nanami
#include<bits/stdc++.h>
#define int long long
#define bt __builtin_popcountll
using namespace std;
const int NN=43;
namespace AE86{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
};
auto write=[](int x,char opt='\n'){
char ch[20];short len=0;if(x<0)x=~x+1,putchar('-');
do{ch[len++]=x%10+(1<<5)+(1<<4);x/=10;}while(x);
for(short i=len-1;i>=0;--i)putchar(ch[i]);putchar(opt);
};
auto swap_=[](int&a,int&b){a^=b^=a^=b;};
}using namespace AE86;
int n,m,x,e[NN],ans,lim,f[1<<20],g[NN];
inline bool check(int s,int opt){
for(int i=1;i<=lim;i++) if(s&(1<<i-1))
if((s^(1<<i-1)|e[i+opt*lim])!=e[i+opt*lim]) return 0;
return 1;
}
namespace WSN{
inline short main(){
freopen("nanami.in","r",stdin);
freopen("nanami.out","w",stdout);
for(int i=1,u,v;i<=m;i++){
if(u>v) swap_(u,v);
if(v<=lim){
e[u]|=1<<v-1;
e[v]|=1<<u-1;
}else if(u>lim){
e[u]|=1<<v-1-lim;
e[v]|=1<<u-1-lim;
}else g[v]|=1<<u-1;
}
for(int i=1;i<(1<<lim);i++) if(check(i,0))
ans=max(ans,f[i]=bt(i));
for(int s=1;s<(1<<lim);s++)
for(int i=1;i<=lim;i++)
if(!(s&(1<<i-1))) f[s|(1<<i-1)]=max(f[s|(1<<i-1)],f[s]);
for(int s=1;s<(1<<lim);s++) if(check(s,1)){
int all=(1<<lim)-1;
for(int i=1;i<=lim;i++) if(s&(1<<i-1)) all&=g[i+lim];
ans=max(ans,bt(s)+f[all]);
}
double wsn=(1.0*x/ans)*(1.0*x/ans)*(ans-1)*ans/2.0;
printf("%.6lf\n",wsn);
return 0;
}
}
signed main(){return WSN::main();}


Topics: greedy algorithm Math dp