[solution] 2021 Niuke OI pre competition training camp - improvement group (Game 1)

Posted by nikko50 on Wed, 06 Oct 2021 02:01:59 +0200

A.

In the optimal scheme a n s [ i ] [ j ] ≤ 17 ans[i][j]\leq17 ans[i][j]≤17

So just put ≤ 17 \leq17 Just connect the sides of the table

Single time dijkstra \text{dijkstra} dijkstra time complexity O ( ( n + m ) log ⁡ n ) O((n+m)\log n) O((n+m)logn) .

If you remove the heap and replace it with a queue, what is the time complexity of this problem O ( 17 n 2 ) O(17n^2) O(17n2) .

#include<bits/stdc++.h>
#define db double 
#define ll long long
#define mkp make_pair
#define pii pair<int,int> 
#define inf 0x3f3f3f3f
#define fi first
#define se second
using namespace std;
const int Maxn=2000*2000+5;
const int mod=998244353;
int P,t,ans[2005][2005],vis[2005][2005];
ll val[Maxn],res;
priority_queue<pii> q;  
int has(int i,int j) {
	return (i-1)*(P-1)+j-1;
}
bool solve(int st) {
	for(int i=1;i<P;i++) ans[st][i]=inf,vis[st][i]=0;
	while(q.size()) q.pop();
	int cnt=P-1;
	q.push(mkp(0,st));
	ans[st][st]=0;
	while(q.size()) {
		int x=q.top().se,tmp=ans[st][x]; q.pop();
		if(vis[st][x]) continue;
		vis[st][x]=1;
		cnt--;
		if(cnt==0) return 1;
		for(int j=max(1,x-20);j<=min(P-1,x+20);j++) {
			int nx=x*j%P;
			if(ans[st][x]+abs(x-j)<ans[st][nx]) {
				ans[st][nx]=ans[st][x]+abs(x-j);
				q.push(mkp(-ans[st][nx],nx));
			}
		}
	}
	return 0;
}
int main() {
	memset(ans,0x3f,sizeof(ans));
	scanf("%d%d",&P,&t);
	val[0]=1;
	for(int i=1;i<(P-1)*(P-1);i++) {
		val[i]=val[i-1]*t%mod;
	}
	for(int i=1;i<P;i++) {
		solve(i);
		for(int j=1;j<P;j++) {
			res=(res+ans[i][j]*val[has(i,j)]%mod)%mod;
		}
	}
	printf("%lld",res);
} 

B.

Consider interval dp.

dp metastasis is very obvious.

But you'll get stuck.

There is a conclusion: the first operation of the interval must be the interval maximum.

Consider how to prove it: if you operate max first and then x, the cost is L + R + L1 + R1; If x is operated first, the cost is Max + R1 + L + L1. Obviously, it is better to operate the maximum first.

According to the transitivity of inequality, each time we exchange Max to the left in the operation sequence, the answer will be better, and the conclusion is proved. (we get the essentially optimal policy 233)

With this pruning, the time complexity O ( n 3 ) O(n^3) O(n3) . (although the complexity has not changed 233)

#include<bits/stdc++.h>
#define db double 
#define ll long long
#define mkp make_pair
#define pii pair<int,int> 
#define inf 0x3f3f3f3f
#define fi first
#define se second
using namespace std;
const int Maxn=2005;
const int mod=998244353;
//Conclusion: the optimal decision must be the maximum of interval [l,r] 
int n,Log[Maxn],a[Maxn],st[Maxn][20],dp[Maxn][Maxn];
ll dp2[Maxn][Maxn],c[Maxn][Maxn]; 
int ask(int l,int r) {
	if(l>r) return 0;
	int k=Log[r-l+1];
	return max(st[l][k],st[r-(1<<k)+1][k]);
}
int main() {
	scanf("%d",&n);
	for(int i=2;i<=n;i++) Log[i]=Log[i/2]+1;
	for(int i=1;i<=n;i++) scanf("%d",&a[i]),st[i][0]=a[i];
	for(int j=1;j<20;j++) {
		for(int i=1;i<=n-(1<<j)+1;i++) {
			st[i][j]=max(st[i][j-1],st[i+(1<<j-1)][j-1]);
		}
	}
	for(int i=0;i<=n;i++) c[i][0]=1;
	for(int i=1;i<=n;i++) {
		for(int j=1;j<=n;j++) {
			c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;
		}
	}
	for(int i=1;i<=n;i++) dp[i][i]=0,dp2[i][i]=1;
	for(int i=1;i<=n+1;i++) dp2[i][i-1]=1;
	for(int len=2;len<=n;len++) {
		for(int i=1;i<=n-len+1;i++) {
			int j=i+len-1;
			dp[i][j]=inf;
			for(int k=i;k<=j;k++) {
				if(a[k]!=ask(i,j)) continue;
				if(dp[i][j]==ask(i,k-1)+ask(k+1,j)+dp[i][k-1]+dp[k+1][j]) {
					dp2[i][j]=(dp2[i][j]+dp2[i][k-1]*dp2[k+1][j]%mod*c[j-i][k-i]%mod)%mod; 
				}
				else if(dp[i][j]>ask(i,k-1)+ask(k+1,j)+dp[i][k-1]+dp[k+1][j]) {
					dp[i][j]=ask(i,k-1)+ask(k+1,j)+dp[i][k-1]+dp[k+1][j];
					dp2[i][j]=dp2[i][k-1]*dp2[k+1][j]%mod*c[j-i][k-i]%mod;
				}
			}
		}
	}
	printf("%lld",dp2[1][n]);
}

C.

Very disgusting simulation problem.

It is easy to see that the answer is the sum of several equal difference sequences.

Violence enumeration i ∈ [ 2 t , 2 t + 1 ) i\in [2^t,2^{t+1}) i ∈ [2t,2t+1), it is not difficult to deduce at first i ∗ ( c − 1 ) m o d    2 t + 1 = 0 i*(c-1)\mod 2^{t+1} = 0 i∗(c−1)mod2t+1=0

hold c − 1 c-1 c − 1 2 2 Factorization of 2, i.e.: i m o d    2 g = 0 i\mod 2^{g}=0 imod2g=0, where g = max ⁡ ( 0 , t + 1 − p ) g=\max(0,t+1-p) g=max(0,t+1−p)

It is not difficult to see two things here:

  1. each 2 g 2^g 2g numbers have the same function value, there are 2 t 2^t 2t number, so there are 2 g − t 2^{g-t} 2g − t groups, and the tolerance between each group is 2 g 2^g 2g
  2. If i < n − 1 i<n-1 If I < n − 1, this group can be divided exactly

Let's review the summation formula of arithmetic sequence: first term * number of items + number of items * (number of items - 1) / 2 * tolerance

Bring in the above formula to get the answer.

Now let's solve it i = n − 1 i=n-1 i=n − 1.

We are divided into pieces and whole pieces.

Scattered blocks are relatively simple, as long as they can be divided 2 g 2^g The 2g part is the whole block (in other words, 1 + the first 2~n-g bits)

The following n-g+1~n bits are all scattered blocks. Since we regard the last scattered blocks as the whole block, we forget more 2 g 2^g 2g - sk - 1, and the last term can be obtained by the first term + (number of terms - 1) * tolerance, so we're done. The time complexity is O(n).

Conclusion: this problem is purely deduced by mathematical methods. The summation of each part is particularly clear. We must have a deep understanding of the nature of the problem.

#include<bits/stdc++.h>
#define db double 
#define ll long long
#define mkp make_pair
#define pii pair<int,int> 
#define inf 0x3f3f3f3f
#define fi first
#define se second
using namespace std;
const int mod=998244353;
const int Maxn=1e7+5;
char s[Maxn];
ll n,m,p,c,res,ksm[Maxn];
//Consider what the sequence dp(i) looks like
//i \in [2^p,2^{p+1})
//i * (c-1)  mod 2^p = 0
//Obviously, when i = 2^p is constant, dp(i) = 2^p
//If c-1 is a multiple of 2^p, this section is the sum of the sequence of equal differences
//  
ll calc(ll sx,ll gc,ll xs) {
	return (sx*xs%mod+xs*(xs-1)/2%mod*gc%mod)%mod;
}
int main() {
//	freopen("data.in","r",stdin);
    ksm[0]=1;
    for(int i=1;i<=1e7;i++) ksm[i]=ksm[i-1]*2%mod;
    int T;
    scanf("%d",&T);
    while(T--) {
    	scanf("%s%lld",s+1,&c),n=strlen(s+1);
  //  	reverse(s+1,s+1+n);
    	int tmp=0;
    	for(int i=1;i<=n;i++) {
    		tmp=tmp*2+s[i]-'0';
		}
//		printf("%d\n",tmp);
        c--;
        if(c&1) {
            printf("0\n");
            continue;
        }
        if(c==0) {
            ll tmp=0;
            for(int i=1;i<=n;i++) {
                tmp=(tmp*2+s[i]-'0')%mod;
            }
            printf("%lld\n",tmp*(tmp+1)/2%mod);
            continue;
        }
        p=0;
        res=0;
        while(c%2==0) p++,c/=2;
        
        for(int i=0;i<n;i++) {
            //Three elements of the arithmetic sequence: first item, tolerance, item number
            //First item * number of items + number of items * (number of items - 1) / 2 * tolerance
            //First item = 2^i
            if(i<n-1) {
            	ll sx=ksm[i],gc=max(i+1-p,0ll),xs=ksm[i-gc];
	            //Tolerance = 2^{max(i+1-p,0)}
	            //Number of items = 2^{i-gc}
	            res=(res+ksm[gc]*calc(sx,ksm[gc],xs)%mod)%mod;
			}
            else {
            	//The number of items can be modeled
		        ll sx=ksm[i],gc=max(i+1-p,0ll),xs=0,sk=0,mx=0;
		        for(int j=1;j<=n-gc;j++) {
		            xs=(xs*2+s[j]-'0')%mod;
		        }
		        xs=(xs-ksm[i-gc]+1+mod)%mod;
		        //Calculate the whole block 
//		        printf("%d %d %d %d\n",sx,ksm[gc],xs,gc);
		        res=(res+ksm[gc]*calc(sx,ksm[gc],xs)%mod)%mod;
		        //The last item was counted 2^g - sk - 1 times 
				 for(int j=n-gc+1;j<=n;j++) {
				 	sk=(sk*2+s[j]-'0')%mod;
				 }
				 mx=(sx+(xs-1)*ksm[gc]%mod)%mod;
				 res=(res-(ksm[gc]-sk-1+mod)%mod*mx%mod+mod)%mod;
		        //Calculate bulk 
//		        res=(res+sk*mx%mod)%mod; 
			}
//			printf("%d\n",res);
        }
        printf("%lld\n",res);
	}
	
	
}

D.

Two dimensional st Table + bitset + bisection.

It's obvious not to say. It's mainly observed a [ i ] [ j ] ≤ 100 a[i][j]\leq100 a[i][j] ≤ 100, so go directly to bitset \text{bitset} bitset (really a violent artifact)

Time complexity O ( n 2 l o g n ) O(n^2logn) O(n2logn). (the constant may be slightly larger 233)

#include<bits/stdc++.h>
#define db double 
#define ll long long
#define mkp make_pair
#define pii pair<int,int> 
#define inf 0x3f3f3f3f
#define fi first
#define se second
using namespace std;
const int Maxn=1505;
//2D st Table + bitset
int n,m,Log[Maxn],a[Maxn][Maxn],k,res;
bitset<101> st[Maxn][Maxn][11];
inline int read() {
	int x=0,f=1; char c=getchar();
	while(c<'0'||c>'9') {
		c=getchar();
	}
	while(c>='0'&&c<='9') {
		x=(x<<1)+(x<<3)+c-'0';
		c=getchar();
	}
	return x;
}
int qry(int x,int y,int d) {
	int k=Log[d];
	return (st[x][y][k]|st[x+d-(1<<k)][y][k]|st[x][y+d-(1<<k)][k]|st[x+d-(1<<k)][y+d-(1<<k)][k]).count();
}
int solve(int x,int y,int k) {
	if(k==0) return 0;
	int l=1,r=min(n-x+1,m-y+1),res=0;
	while(l<=r) {
		int mid=l+r>>1;
		if(qry(x,y,mid)<=k) res=mid,l=mid+1;
		else r=mid-1;
	}
	return res;
}
int main() {
	n=read(),m=read(),k=read();
	for(int i=2;i<=max(n,m);i++) {
		Log[i]=Log[i/2]+1;
	}
	for(int i=1;i<=n;i++) {
		for(int j=1;j<=m;j++) {
			scanf("%d",&a[i][j]);
			st[i][j][0][a[i][j]]=1; 
		}
	}
	for(int k=1;k<=10;k++) {
		for(int i=1;i<=n-(1<<k)+1;i++) {
			for(int j=1;j<=m-(1<<k)+1;j++) {
				st[i][j][k]=st[i][j][k-1]|st[i+(1<<k-1)][j][k-1]|st[i][j+(1<<k-1)][k-1]|st[i+(1<<k-1)][j+(1<<k-1)][k-1];
			}  
		}
	}
	for(int i=1;i<=n;i++) {
		for(int j=1;j<=m;j++) {
			int tmp=solve(i,j,k);
			if(!tmp||qry(i,j,tmp)!=k) continue;
			res+=tmp-solve(i,j,k-1);
		}
	}
	printf("%d",res);
}

Topics: Algorithm Math