Training summary from June 24 to 25, 2021

Posted by j-dearden on Tue, 25 Jan 2022 15:11:15 +0100

Training portal: CUGBACM19 summer training #2 (special topic of Basic Mathematics) - Virtual Judge (vjudge.net)

I feel that there are still too many board questions, but I'm too good to do half of them. I think it's all a variety of boards. I just sort them out here in case I forget something in the future.

A - combination parity (HDU 6129)

Original title link: acm.hdu.edu.cn

Obviously, since n is 2e5 and m is 1e9, direct simulation / violent operation must not work

Note that a^b=c, (a^b)^b=a; Considering that after each operation, the front part of the position index has a great impact on the value of the following elements, we can consider the parity of the influence times of each element on the XOR of the following elements to judge whether the element at this position contributes to the XOR result of the following elements, so as to calculate the value of each element.

Considering the contribution times of element a1 to subsequent elements:

                 a2      a3      a4      a5      a6......

When m=0: 0 ﹐ 0 ﹐ 0

When m=1: 1 # 1 # 1 # 1 (because the XOR update of each subsequent number must contain a1)

When m=2: 1 ﹐ 2 ﹐ 3 ﹐ 4 ﹐ 5

When m=3: 1 ﹐ 3 ﹐ 6 ﹐ 10 ﹐ 15

......

It can be observed that after the K + 1st operation, p[k+1][wz]=sigma(p[k][i]), i=1,2,3... wz

Then this is a simple board of repeated addition, in which the element value in row I and column j is C(j-1,m+i-1), and the value is 0 when m=0

After finding the general formula of combinatorial number, we only need to judge its parity. For combinatorial number C(m,n), if M & n = = m, the value of combinatorial number is odd, otherwise it is even.

Code (G + +):

#include<iostream>
#define ll long long
using namespace std;
ll s[200005],p[200005];
bool zhsjo(ll m,ll n){
	return (n&m)==m;
}
int main(){
	ll t,n,m,i,j,k;
	scanf("%lld",&t);
	while(t--){
		scanf("%lld%lld",&n,&m);
		for(i=1;i<=n;i++) scanf("%lld",&s[i]),p[i]=s[i];
		for(i=1;i<=n-1;i++){
			if(zhsjo(i,m+i-1)==1){
				for(j=1;j<=n-i;j++) p[j+i]^=s[j];
			}
		}
		for(i=1;i<=n;i++){
			cout<<p[i];
			if(i<n) cout<<" ";
		}
		cout<<endl;
	}
    return 0;
}

B - Cartesian tree + tree isomorphic expectation (to be supplemented)

C - delete subtree expectation (CF 280C)

Original title link: Problem - 280C - Codeforces

(actually, it's only after consulting Cao Lao qwq)

Mathematical induction, considering chain structure; Ordinary situation: n==1. It is expected to be 1

When n=k, let the current expected number of steps be q, then when n=k+1, there are the following two cases:

1. If there is a probability of k/(k+1), take the first k nodes, and the expectation at this time is q*k/(k+1)

2. If the newly added node is obtained from the probability of 1/(k+1), then the problem subproblem becomes the case of n=k (expected steps + 1), and the expectation at this time is (q+1)/(k+1)

By adding 1 and 2, the sum is q+1/(k+1), which generally proves that the expected contribution of the newly added node is 1/(k+1)

In the tree structure, in order to make each newly added node have no impact on the original n nodes, it can be seen that the node at this time must be a leaf node. According to the induction of chain structure, the expected contribution at this time is 1/(d+1), where d is the depth of the point (i.e. the number of layers)

After finding the relationship, simple sequence traversal bfs is OK.

Code (GNU C++14):

#include<iostream>
#include<iomanip>
#include<vector>
#include<queue>
#define ll long long
using namespace std;
vector<ll>s[100005];
queue<pair<ll,ll> >cc;
pair<ll,ll>zczc;
ll p[100005];
long double su=0;
int main(){
	ll n,i,j,k,zc,a,b;
	char fh='\0';
	scanf("%lld",&n);
	getchar();
	for(i=1;i<=n-1;i++){
		scanf("%lld%lld",&a,&b);
		s[a].push_back(b);
		s[b].push_back(a);
	}
	cc.push({1LL,1LL});
	while(cc.size()>0){
		zczc=cc.front();
		cc.pop();
		if(p[zczc.first]==1) continue;
		p[zczc.first]=1;
		//cout<<zczc.second<<"---"<<endl;
		su+=1.0/(zczc.second);
		if(s[zczc.first].size()>0){
			for(i=0;i<=s[zczc.first].size()-1;i++){
				if(p[s[zczc.first][i]]==0){
					cc.push({s[zczc.first][i],zczc.second+1});
				}
			}
		}
	}
	cout<<fixed<<setprecision(9)<<su;
    return 0;
}

D - Lindstr ö m – Gessel – Viennot theorem (to be supplemented)

E - Euler power reduction formula (to be supplemented)

F - johnson's Law (HDU 6299)

Original title link: acm.hdu.edu.cn

Simple greedy question (it seems that it has nothing to do with the topic name awa). For each bracket string sequence, first link it in the following way:

1. The sequence with all left parentheses is better than all other sequences.

2. The sequence with all right parentheses is inferior to all other sequences.

In short, the left parentheses should be arranged first.

However, for sequence () ((and sequence (()), the latter must precede the former, otherwise the left parenthesis will not match.

Then, for each sequence, we calculate the following three parameters in advance:

-1: Number of isolated left parentheses (refers to the number not paired with the right parenthesis in the sequence)

-2: Number of isolated right parentheses

-3: Number of paired bracket groups (to facilitate subsequent processing and addition, there is no need to re scan one bracket string)

Then, for other bracket strings:

3. Only the sequence with isolated left parenthesis is better than other sequences.

4. Only the sequence with isolated right parentheses is inferior to other sequences.

5. If there are many isolated left parentheses, they shall be arranged in priority; If there are few isolated right parentheses, they will be arranged first.

After sorting, the total length of the legal sequence is:

(number of legal bracket groups contained in each legal sequence + matching logarithm of isolated left bracket and isolated right bracket) * 2

Code (G + +):

#include<iostream>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
struct node{
	ll z,y,sz,sl;
}s[100001];
char sr[100001];
void cl(ll cd,ll &a,ll &b,ll &sl){
	ll i,j,zc=0;
	for(i=0;i<=cd-1;i++){
		if(zc==0 and sr[i]==')') b++;
		if(zc!=0 and sr[i]==')') zc--,sl+=2;
		if(sr[i]=='(') zc++;
	}
	a+=zc;
}
bool cmp(node x,node y){
	if(x.y>=x.z and y.y<y.z) return 0;
    if(x.y<x.z and y.y>=y.z) return 1;
    if(x.y<x.z and y.y<y.z) return x.y<y.y;
    else return x.z>y.z;
}
int main(){
	ll t,n,i,j,k,a,b,zc,su;
	scanf("%lld",&t);
	while(t--){
		scanf("%lld",&n);
		for(i=1;i<=n;i++){
			scanf("%s",sr);
			a=b=zc=0;
			cl(strlen(sr),a,b,zc);
			s[i].z=a;
			s[i].y=b;
			s[i].sz=a-b;
			s[i].sl=zc;
		}
		sort(s+1,s+1+n,cmp);
		for(i=1,a=su=0;i<=n;i++){
			su+=s[i].sl;
			if(i==1 or i==n){
				if(i==1) a+=s[i].z;
				else{
					su+=min(a,s[i].y)*2;
					break;
				}
			}
			else{
				zc=min(a,s[i].y);
				su+=zc*2;
				a-=zc;
				a+=s[i].z;
			}
		}
		printf("%lld\n",su);
	}
    return 0;
}

G - absolute inequality (HDU 6343)

Original title link: acm.hdu.edu.cn

I haven't seen you for a long time qwq

First, there is the absolute value inequality | A-B | + | B-C | > = | a-c |, which can be proved by the geometric meaning of the number axis distance.

And: for sqrt(|a-b|)+sqrt(|b-c|) and sqrt(|a-c|)

The squares on both sides are: | a-b|+|b-c|+2*sqrt(a-b)*sqrt(b-c) and | a-c|. The root sign is non negative, and the former is larger.

So we can know: sqrt (|a-b|) + sqrt (|b-c|) > = sqrt (|a-c|)

The answer is to round the distance from the first point to the last point in the departure direction.

Code (G + +):

#include<iostream>
#include<algorithm>
#include<cmath>
#define ll long long
#define dd long double
using namespace std;
int main(){
	ll t,n,i,j,a,b,zc;
	cin>>t;
	while(t--){
		cin>>n;
		for(i=1;i<=n;i++){
			cin>>zc;
			if(i==1) a=zc;
			if(i==n) b=zc;
		}
		cout<<int(sqrt(abs(b-a)))<<endl;
	}
    return 0;
}

H - Abel theorem (to be supplemented)

I - simpson integral (HDU 1724)

Original title link: acm.hdu.edu.cn

I don't know what simpson integral is. I directly find the qwq of the assignment of the original function

Code (G + +):

#include<iostream>
#include<cmath>
#define ll long long
#define dd double
using namespace std;
dd a,b,l,r;
dd F(dd x){
	dd zc=acos(x);
	return zc/2-sin(2*zc)/4;
}
int main(){
	ll t,sl;
	dd i,j,k,su,dx,n;
	scanf("%lld",&t);
	while(t--){
		scanf("%lf%lf%lf%lf",&a,&b,&l,&r);
		su=2*a*b*(F(l/a)-F(r/a));
		printf("%.3lf\n",su);
	}
    return 0;
}

J - generalized Fibonacci cycle section (to be supplemented)

K - Euler number (HDU 1418)

Original title link: acm.hdu.edu.cn

It should be the most popular check-in question in the audience. Just push it. The answer is n+m-2

Code (G + +):
 

#include<iostream>
#define ll long long
using namespace std;
int main(){
	ll m,n;
	while(cin>>n>>m){
		if(n==0 and m==0) break;
		cout<<n-2+m<<endl;
	}
    return 0;
}

L - LUCAS (to be supplemented)

M - Pr ü fer code (to be supplemented)

N - Wilson theorem (HDU 5391)

Original title link: acm.hdu.edu.cn

The conclusion is quite simple and the realization is a little difficult qwq

When n is prime, (n-1)!%n=n-1, when n is not prime, (n-1)!%n=0

However, because t is 1e5 and N is 1e9, the root number n is simple, the method will TLE, and Euler sieve will MLE, so I went to Luogu bp for a Miller Rabin qwq, and then passed qwq

Code (G + +):

#include<iostream>
#include<cmath>
#define ll long long
#define lll __int128
using namespace std;
//Ps: Miller Rabin copied from luo_ Gu (not qwq for the time being)
ll max_factor;
template<class type_name> inline type_name qr(type_name sample)
{
    type_name ret=0,sgn=1;
    char cur=getchar();
    while(!isdigit(cur))
        sgn=(cur=='-'?-1:1),cur=getchar();
    while(isdigit(cur))
        ret=(ret<<1)+(ret<<3)+cur-'0',cur=getchar();
    return sgn==-1?-ret:ret;
}
inline ll gcd(ll a,ll b)
{
    if(b==0)
        return a;
    return gcd(b,a%b);
}

inline ll qp(ll x,ll p,ll mod)
{
    ll ans=1;
    while(p)
    {
        if(p&1)
            ans=(lll)ans*x%mod;
        x=(lll)x*x%mod;
        p>>=1;
    }
    return ans;
}

inline bool mr(ll x,ll b)
{
    ll k=x-1;
    while(k)
    {
        ll cur=qp(b,k,x);
        if(cur!=1 && cur!=x-1)
            return false;
        if((k&1)==1 || cur==x-1)
            return true;
        k>>=1;
    }
    return true;
}

inline bool prime(ll x)
{
    if(x==46856248255981ll || x<2)
        return false;
    if(x==2 || x==3 || x==7 || x==61 || x==24251)
        return true;
    return mr(x,2)&&mr(x,61);
}

inline ll f(ll x,ll c,ll n)
{
    return ((lll)x*x+c)%n;
}
inline ll PR(ll x)
{
    ll s=0,t=0,c=1ll*rand()%(x-1)+1;
    int stp=0,goal=1;
    ll val=1;
    for(goal=1;;goal<<=1,s=t,val=1)
    {
        for(stp=1;stp<=goal;++stp)
        {
            t=f(t,c,x);
            val=(lll)val*abs(t-s)%x;
            if((stp%127)==0)
            {
                ll d=gcd(val,x);
                if(d>1)
                    return d;
            }
        }
        ll d=gcd(val,x);
        if(d>1)
            return d;
    }
}
int main(){
	ll t,n,i,j,k,su;
	scanf("%lld",&t);
	while(t--){
		scanf("%lld",&n);
		if(n<=10){
			for(i=su=1;i<=n-1;i++){
				su*=i;
				su%=n;
			}
			printf("%lld\n",su);
		}
		else{
			if(prime(n)) printf("%lld\n",n-1);
			else printf("0\n");
		}
	}
    return 0;
}

O - Pythagorean triples (to be completed)

P - Legendre theorem (HDU 3988)

Original title link: acm.hdu.edu.cn

In positive number n! In the standard factorization of prime factors, if the highest exponent of prime p is recorded as Lp(n!)

LP (n!)= Sigma (n / (P ^ k)), k > = 1 -- from Baidu Encyclopedia

The board problem of Legendre's theorem. Since k is not necessarily a prime number, the prime factor of k is decomposed. After calculating the times of each prime factor, Legendre's theorem is executed to maintain the minimum value of all prime factors.

Euler screen is required to maintain the quality factor within 1e8.

Since the scale of k is 1e14 and the scale of n is 1e18, it is best to use division when judging the power, otherwise it is easy to explode long long.

Code (G + +):

#include<iostream>
#include<cmath>
#define ll long long
using namespace std;
bool s[10000001];
ll p[1000001];
int main(){
	ll t,k,dq,n,m,i,iii,j,zc,sl=0,slsl,dqdq,zx;
	for(i=2;i<=10000000;i++){
		if(s[i]==0) p[++sl]=i;
		for(j=1;j<=sl and p[j]*i<=10000000;j++){
			s[i*p[j]]=1;
			if(i%p[j]==0) break;
		}
	}
	scanf("%lld",&t);
	for(iii=1;iii<=t;iii++){
		scanf("%lld%lld",&n,&k);
		printf("Case %lld: ",iii);
		if(k==1){
			printf("inf\n");
			continue;
		}
		for(i=2,zx=1e18;i<=sqrt(k);i++){
			if(k%i==0){
				slsl=0;
				while(k%i==0) slsl++,k/=i;
				dq=1,dqdq=0;
				while(dq<=n*1.0/i){
					dq*=i;
					dqdq+=n/dq;
				}
				zx=min(zx,dqdq/slsl);
			}
		}
		if(k!=1){
			i=k;
			slsl=1;
			dq=1,dqdq=0;
			while(dq<=n*1.0/i){
				dq*=i;
				dqdq+=n/dq;
			}
			zx=min(zx,dqdq/slsl);	
		}
		printf("%lld\n",zx);
	}
    return 0;
}

Q - fari sequence (to be supplemented)

R - bell number (HDU 2512)

Original title link: acm.hdu.edu.cn

The second kind of board problem of Stirling number.

According to its recurrence formula, the state transition equation can be obtained: dp[i][j]=dp[i-1][j-1]+j*dp[i-1][j]

Then, because the elements are out of order, the obtained answer can be output directly.

Code (G + +):

#include<iostream>
#define ll long long
using namespace std;
ll s[2005][2005],p[2005],mod=1000;
int main(){
	ll t,n,i,j,k,su;
	s[1][1]=1;
	for(i=2;i<=2000;i++){
		for(j=1;j<=i;j++){
			s[i][j]=s[i-1][j-1]+j*s[i-1][j];
			s[i][j]%=mod;
		}
	}
	for(i=1;i<=2000;i++){
		for(j=su=0;j<=i;j++){
			su+=s[i][j]%mod;
			su%=mod;
		}
		p[i]=su;
	}
	scanf("%lld",&t);
	while(t--){
		scanf("%lld",&n);
		printf("%lld\n",p[n]);
	}
    return 0;
}

S - stirling number (HDU 2643)

Original title link: acm.hdu.edu.cn

It is still the board problem of the second kind of Stirling number.

It should be noted that since the elements are ordered, they need to be multiplied by their factorials.

That is, the answer is sigma (DP [i] [J] * (J!), i<=n,j<=m

Code (G + +):

#include<iostream>
#define ll long long
using namespace std;
ll s[105][105],p[105],mod=20090126;
ll jc(ll x){
	ll i,s=1;
	for(i=1;i<=x;i++){
		s*=i;
		s%=mod;
	}
	return s;
}
int main(){
	ll t,n,i,j,k,su;
	s[1][1]=1;
	for(i=2;i<=100;i++){
		for(j=1;j<=i;j++){
			s[i][j]=s[i-1][j-1]+j*s[i-1][j];
			s[i][j]%=mod;
		}
	}
	for(i=1;i<=100;i++){
		for(j=su=0;j<=i;j++){
			su+=s[i][j]*jc(j)%mod;
			su%=mod;
		}
		p[i]=su;
	}
	scanf("%lld",&t);
	while(t--){
		scanf("%lld",&n);
		printf("%lld\n",p[n]);
	}
    return 0;
}

T - polya theorem (to be supplemented)

U - pick theorem (POJ 2954)

Original title link: 2954 -- Triangle (poj.org)

Lattice triangle problem. Area of grid point triangle = (number of internal fixed points of grid point triangle + number of edge vertices / 2 + 1)

Then the number of internal lattice points is required, as long as the area and the number of edge vertices are calculated. The formula of area vector will not lose accuracy, and the number of edge fixed points only needs to be calculated once gcd.

Code (G + +):

#include<iostream>
#include<algorithm>
#include<cmath>
#define ll long long
using namespace std;
ll jdz(ll n){
	if(n<0) return -n;
	else return n;
}
ll gcd(ll a,ll b){
	if(a==0 or b==0){
		if(a==0) return b;
		else return a;
	}
	return __gcd(a,b);
}
int main(){
	ll x1,x2,x3,y1,y2,y3,i,j,k,a,b,c,d,s2,aa,bb,cc;
	while(cin>>x1>>y1>>x2>>y2>>x3>>y3){
		if(x1==0 and y1==0 and x2==0 and y2==0 and x3==0 and y3==0) break;
		a=x2-x1;
		b=y2-y1;
		c=x3-x1;
		d=y3-y1;
		s2=jdz(a*d-b*c);
		bb=0;
		bb+=gcd(jdz(x1-x2),jdz(y1-y2))-1;
		bb+=gcd(jdz(x1-x3),jdz(y1-y3))-1;
		bb+=gcd(jdz(x3-x2),jdz(y3-y2))-1;
		bb+=3;
		aa=ceil((s2-bb+1)/2.0);
		cout<<aa<<endl; 
	}
    return 0;
}

V - fast Walsh transform (to be supplemented)

W - bsgs (to be supplemented)

X - pell equation (I also want to know where the original problem is qwq)

First, replace by the sum of squares, x^2=(n+1)*(2*n+1)/6

Note that (n+1,2*n+1)=1, then x^2 is divided into a^2 and b^2, where (a^2,b^2)=1

1. 6*a^2=n+1,b^2=2*n+1, and 12*a^2-b^2=1

2. 3*a^2=n+1,2*b^2=2*n+1. At this time, there are 6*a^2-2*b^2=1, left even and right odd, rounding off.

3. 2*a^2=n+1,3*b^2=2*n+1. At this time, there are 4*a^2-3*b^2=1

At this time, 4*a^2=1+3*b^2. According to the meaning of module 4, b must be an odd number (Touch 4 on both sides must be 0)

Then: from 3*b^2=2*n+1, we can know that n must be an even number.

Because the formula 2*a^2=n+1, left even and right odd, contradictory, round off.

4. a^2=n+1,6*b^2=2*n+1. At this time, there are 2*a^2-6*b^2=1, left even and right odd, rounding off.

After that, there is only one indefinite equation 12*a^2-b^2=1. Since the coefficient of 12 is not small, this equation obviously has few sets of solutions. Next, we can calculate it violently.

Finally, several groups of solutions (n,k) in 1e16 are solved, and the table can be printed.

Code (G + +):

#include<iostream>
#define ll long long
using namespace std;
int main(){
	ll n;
	while(cin>>n){
		if(n==0) break;
		if(n>=18002650033695937) printf("18002650033695937 10393834843080975\n");
		else{
			if(n>=92799630902161) printf("92799630902161 53577891882061\n");
			else{
				if(n>=478361323441) printf("478361323441 276182038859\n");
				else{
					if(n>=2465845537) printf("2465845537 1423656585\n");
					else{
						if(n>=12710881) printf("12710881 7338631\n");
						else{
							if(n>=65521) printf("65521 37829\n");
							else{
								if(n>=337) printf("337 195\n");
								else printf("1 1\n");
							}
						}
					}
				}
			}	
		}
	}
    return 0;
}

Y - linear basis (to be supplemented)