# Simulation 89 exam summary

What can I say?

### Pass the exam

T1 mental retardation problem, written for an hour, the result is that the boundary is wrong and hung as 80; The T2 construction idea is correct because the variable name is written incorrectly and hung as 25
Because I didn't know how to use the checker correctly, I wasted more than half an hour doing this
T3 is a few \ (log \) practices that everyone can do. It seems that only I fight violence. I can even live in blocks, but I have no dream
T4 was greedy and covered 48 points with a file error. He was violent like a clown
The expected score is 280 and the actual score is 130. It is difficult not to be at the bottom
namespace_std's problem is very good, but it feels like a waste

### T1. Factorial of mystery

Water question
It is found that the given number can be expressed in the form of continuous multiplication, which is nothing more than determining the multiplication of several numbers and what to start from
First of all, he can express himself, which is directly included in the answer
The dichotomy I use to multiply two and three numbers to see if there is an integer solution that meets the conditions
Directly preprocess more than four numbers, enumerate all numbers whose product is within \ (10 ^ {18} \) and throw them into the map
Complexity is not a problem at all

```#include <bits/stdc++.h>
using namespace std;
#define int long long
#define mp make_pair
map <int,int> p[20];
set <pair<int,int> >ans;
signed main()
{
freopen("factorial.in","r",stdin);
freopen("factorial.out","w",stdout);
for(int i=4;i<=18;i++)
{
int s=1;for(int j=1;j<=i;j++)s=s*j;
for(int j=i+1;j<=1e18;j++)
{
s/=(j-i);s*=j;
if(s>1e18)break;
p[i].insert(mp(s,j-i+1));
}
}
int t;cin>>t;
while(t--)
{
int x;scanf("%lld",&x);
if(x==1){puts("-1");continue;}
ans.clear();ans.insert(mp(x,x-1));
int l=2,r=1e9,an=0;
while(l<=r)
{
int mid=(l+r)>>1;
if(mid*(mid+1)==x){an=mid;break;}
else if(mid*(mid+1)<x)l=mid+1;
else r=mid-1;
}
if(an)ans.insert(mp(an+1,an-1));
l=3,r=1e6,an=0;
while(l<=r)
{
int mid=(l+r)>>1;
if(mid*mid*mid-mid==x){an=mid;break;}
else if(mid*mid*mid-mid<x)l=mid+1;
else r=mid-1;
}
if(an)ans.insert(mp(an+1,an-2));
for(int i=4;i<=18;i++)
{
if(p[i].find(x)==p[i].end())continue;
int ga=p[i][x];
ans.insert(mp(ga+i-1,ga-1));
}
printf("%lld\n",(int)ans.size());
for(auto it=ans.begin();it!=ans.end();it++)
printf("%lld %lld\n",(*it).first,(*it).second);
}
return 0;
}
```

### T2. Subset

Divide the number of \ (n \) into \ (n/k \) groups, with the number of \ (k \) in each group
It is found that if the number of groups is even, you can spell them directly
For odd numbers, only three groups need to be processed, and the rest are even numbers
The first group \ (1-n \) is arranged in order. The second group considers pulling it up, that is \ (2,3,4,5,1 \)
But we can't pull less. We should make the third group spell the desired answers. Then how much to pull can be calculated at the beginning
Then see how much is missing, fill in the third group, so that it must not be heavy or missing, and then the big simulation
Pay attention to the boundary and special judgment

```#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=1000050;
vector <int> ans[N];
int n,k,lk,a[N],tot;
signed main()
{
freopen("subset.in","r",stdin);
freopen("subset.out","w",stdout);
int t;cin>>t;
while(t--)
{
scanf("%lld%lld",&n,&k);
int sum=((n+1)*n)/2;
if(sum%k){puts("No");continue;}
for(int i=1;i<=lk;i++)ans[i].clear();
lk=k;int s=n/k;
if(s&1)
{
if(k==1)
{
puts("Yes");
for(int i=1;i<=n;i++)printf("%lld ",i);
puts("");continue;
}
if(s==1){puts("No");continue;}
for(int i=1;i<=s-3;i++)
{
int l=(i-1)*k+1,r=l+k-1;
if(i&1)for(int j=1;j<=k;j++)ans[j].push_back(l+j-1);
else for(int j=1;j<=k;j++)ans[j].push_back(l+(k-j+1)-1);
}
int ss=((k+1)*k)/2;ss*=3;assert(ss%k==0);int num=ss/k;
int l=(s-3)*k+1,r=l+k-1,p=num-k-1;tot=0;
for(int i=1;i<=k;i++)ans[i].push_back(l+i-1);
l+=k;r+=k;
for(int i=1;i<=k-p+1;i++)ans[i].push_back(l+(p+i-1)-1),a[++tot]=p+i-1;
for(int i=k-p+2;i<=k;i++)ans[i].push_back(l+(i-(k-p+1))-1),a[++tot]=i-(k-p+1);
l+=k;r+=k;
for(int i=1;i<=k;i++)ans[i].push_back(l+num-a[i]-i-1);
}
else
{
for(int i=1;i<=s;i++)
{
int l=(i-1)*k+1,r=l+k-1;
if(i&1)for(int j=1;j<=k;j++)ans[j].push_back(l+j-1);
else for(int j=1;j<=k;j++)ans[j].push_back(l+(k-j+1)-1);
}
}
puts("Yes");
for(int i=1;i<=k;i++)
{
for(int j=0;j<ans[i].size();j++)
printf("%lld ",ans[i][j]);
putchar('\n');
}
}
return 0;
}
```

### T3. Concrete powder

The conversion problem is interval addition. Ask when a position is greater than or equal to \ (y \) at the earliest
The positive solution is an off-line way of immortals. Open the tree array with time as the subscript, and then hang the query and modification to the original sequence
Then scan the original sequence. For a modification, insert it when scanning to the left endpoint and delete it at the right endpoint
After inserting and before deleting, answer the query. Here, we use the first-hand multiplication of nb on the tree array
It is to find the prefix and the minimum subscript greater than or equal to \ (x \). By analogy with multiplication on a tree, it is not difficult to understand the principle of tree array
The examination room won't series. When can the data structure love me

```#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=1000060;
int n,q;
struct bit{
int b[N];
inline int lowbit(int x){return x&(-x);}
{
for(int i=p;i<=q;i+=lowbit(i))
b[i]+=v;
}
inline int get(int lim,int v)
{
int x=0;
for(int i=20;i>=0;i--)
{
if((x|(1<<i))<=lim&&b[x|(1<<i)]<v)x|=1<<i,v-=b[x];
}
if(x==lim)return 0;
else return x+1;
}
}tr;
vector <pair<int,int> > p1[N],p2[N],p3[N];
int ans[N],op[N];
signed main()
{
freopen("concrete.in","r",stdin);
freopen("concrete.out","w",stdout);
cin>>n>>q;
for(int i=1;i<=q;i++)
{
scanf("%lld",&op[i]);
if(op[i]&1)
{
int x,l,r;scanf("%lld%lld%lld",&l,&r,&x);
p1[l].push_back(make_pair(i,x));
p2[r].push_back(make_pair(i,x));
}
else
{
int x,y;scanf("%lld%lld",&x,&y);
p3[x].push_back(make_pair(i,y));
}
}
for(int i=1;i<=n;i++)
{
for(int j=0;j<p3[i].size();j++)ans[p3[i][j].first]=tr.get(p3[i][j].first,p3[i][j].second);
}
for(int i=1;i<=q;i++)if(!(op[i]&1))printf("%lld\n",ans[i]);
return 0;
}
```

### T4. Drainage system

Different from the original question, there is a damage value and probability. Let's find the expectation
If a tube breaks down, the contribution from \ (x \) to \ (y \) decreases and the contribution from \ (x \) to others increases
Then you can calculate how much to add or subtract. Since other increases can be regarded as \ (x \) increases, multiply by a probability
However, if you write directly, you will get a high score of 36. Note that the traffic here is relatively not bad, so you should first calculate the traffic \ (s1 \) that is not bad, and then perform the above addition and subtraction based on \ (s1 \)

```#include <bits/stdc++.h>
using namespace std;
#define int long long
{
int x=0;char ch=getchar();
while(ch<'0'||ch>'9')ch=getchar();
while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return x;
}
const int M=500050,N=200050;
const int mod=998244353;
inline int ksm(int x,int y)
{
int s=1;x%=mod;
for(;y;y>>=1)
{
if(y&1)s=s*x%mod;
x=x*x%mod;
}
return s;
}
struct node{
int from,to,next,w;
}a[M];
inline void add(int x,int y,int z)
{
a[mm].from=x;a[mm].to=y;a[mm].w=z;
}
int n,m,r,k,du[N],to[N],s[N],ss[N],duu[N];
int inv[M],ga,sum;queue <int> q;
inline void gankp1()
{
memcpy(duu,du,sizeof(duu));
for(int i=1;i<=n;i++)if(!duu[i])q.push(i);
while(q.size())
{
int x=q.front(),w=ss[x]*inv[to[x]]%mod;q.pop();
{
int y=a[i].to;ss[y]=(ss[y]+w)%mod;
duu[y]--;if(!duu[y])q.push(y);
}
}
}
inline void gankp2()
{
for(int i=1;i<=n;i++)if(!du[i])q.push(i);
while(q.size())
{
int x=q.front(),w=ss[x],num=to[x];q.pop();
int p1=w*inv[num]%mod,p2=w*inv[num-1]%mod,pp=(p2-p1+mod)%mod;
{
int y=a[i].to,p=a[i].w*ga%mod;
s[x]=(s[x]+p*pp%mod*num%mod)%mod;
s[y]=(s[y]-(pp+p1)%mod*p%mod+mod)%mod;
}
{
int y=a[i].to;s[y]=(s[y]+s[x]*inv[num]%mod)%mod;
du[y]--;if(!du[y])q.push(y);
}
}
}
signed main()
{
freopen("water.in","r",stdin);
freopen("water.out","w",stdout);
cin>>n>>m>>r>>k;
for(int i=1;i<=k;i++)
{
}
for(int i=1;i<=m;i++)s[i]=ss[i]=1;
inv[0]=inv[1]=1;for(int i=2;i<=k;i++)inv[i]=(mod-mod/i)*inv[mod%i]%mod;
ga=ksm(sum,mod-2);gankp1();gankp2();
for(int i=n-r+1;i<=n;i++)printf("%lld ",s[i]);
return 0;
}
```

### Examination summary

I feel the problem is still very big, especially when I feel good but the result is very bad
You can't point to yourself like CSP. You should be stable, shoot and look at the boundary
I should have learned a lot, so we should pay attention to the next game

Tags: Binary Indexed Tree

Posted on Thu, 04 Nov 2021 18:50:43 -0400 by tacojohn