CSP tree in front of the school gate

Keywords: data structure Dynamic Programming

Preliminary ideas:

  1. Preprocess the prime number array [68] within 340 (because if the number greater than 340 is a composite number, it must be divided by the number within 340 (if not, it must be greater than 1e5). Then judge to decompose the prime factor. Just remove the prime number array one by one. Finally, if it is not 1, it will be the last prime number)
  2. For finding the number of perfect species in [al,ar), factor ar al to obtain all factors (not necessarily prime factors), and then detect one by one. If it can be divided by am AI, it will be eliminated. The last remaining number is the number of perfect species with Al and Ar as the boundary
  1. Let g[i][j] represent the number of scheme types with [i,j) as the boundary, f[i][j] Represents the number of all schemes from I to j; after all, it is wrong, the state transition equation is wrong, and the correct relationship is not found; first, f must be composed of a combination and a single body, and the combination is the same, so for any case of F, it can be regarded as inserting several nodes between ij for segmentation, and f_ij is the sum of all cases. Obviously, this is the case If it is difficult to find, it should be decomposed into simple problems. The decomposition action is generally measured by something, and all the conditions of this thing can represent all the conditions of the original problem = =. In this problem, we take the length of the single body composed of the last dividing line and the end as the measurement standard. The conditions in front of this dividing line are arbitrary, then In this way (the length range is [1, j-i-1] + g{I, J}) can indeed cover all cases
  2. Since there is no greater than relationship between intervals, length recursion should be adopted here, and since I and J will not be repeated, the solution of g will not be repeated; when the length is 1, the result of g can be assigned to f. later, g can be solved directly in the current step, and f can be solved directly by recursion
  3. As expected, timeout! Obviously, after all, there are so many obvious repeated operations for each obs[j]-obs[i]
    All factors have to be calculated, which will inevitably time out. Then, this time, I finally understand what is called the tabulation operation of number theory topics, that is, for the values that may be frequently reused in number theory operations, preprocess them in advance, and directly find them linearly when they are used. Although it may seem that the amount of data may be huge during preprocessing, it is not worth it, in fact, after simple processing Mathematical analysis will find that this will reduce a lot of repetitive work (ideological and Political Education: experience is indeed important, but before using experience, it should be considered through rational judgment!)

TLE Code:

//#include<bits/stdc++.h>
#include<iostream>
#define LOCAL
using namespace std;
typedef long long ll;
//Long integers must be used here, because even if mod is an integer, overflow will occur as long as two numbers are multiplied

const ll maxn=1010;
const ll mod=1e9+7;
// int prm[70];int pn;
ll obs[maxn];
ll dp[maxn];

ll read(){
    ll s=0,f=1,c=getchar();
    while (c<'0' || c>'9' ) { if (c=='-') f=-1; c=getchar();}
    while (c>='0' && c<='9') {s=(s<<1)+(s<<3)+c-'0';c=getchar();}
    return f*s;
}
// Euclidean sieve to achieve prime arrays within 340
// int mark[340];
// int get_prm(){
// 	for (int i=2;i<340;++i) mark[i]=1;
// 	int k=0;
// 	for (int i=2;i<340;++i){
// 		if (mark[i]) prm[k++]=i;
// 		for (int j=0;j<k;++j){
//             if (prm[j]*i>=340) break;
// 			mark[prm[j]*i]=0;
// 			if (i%prm[j]==0) break;
// 		}
// 	}
// 	return k;
// }

ll get_g(int i,int j){
	int cont=0;
	ll dft=obs[j]-obs[i];
	if (j==i+1 && dft>1) cont++;
	// get facts
	for (int k=2;k*k<=dft;++k){
		 if (dft%k==0){
		 	int flag=1;
		 	for (int m=i+1;m<=j-1;++m){
		 		if ((obs[m]-obs[i])%k==0){ flag=0;break;}
		 	}
		 	if (flag) cont++;
		 	ll tmpk=dft/k;
		 	if (tmpk==k) continue;
            flag=1;
		 	for (int m=i+1;m<=j-1;++m){
		 		if ((obs[m]-obs[i])%tmpk==0){ flag=0;break;}
		 	}
		 	if (flag) cont++;
	    }
		cont%=mod;
	}
	return cont;
}	
	
int main(){
    #ifdef LOCAL
    freopen("input.txt","r",stdin);
    #endif
    ll n=read();
    for (int i=0;i<n;++i){
    	
    	obs[i]=read();
	}
	// pn=get_prm();	// pn --> the number of prime in [2,340);
	for (int i=1;i<n;++i){
		for (int j=1;j<i;++j){
			dp[i]=(dp[i]+dp[j]*get_g(j,i)%mod)%mod;
		}
		dp[i]=(dp[i]+get_g(0,i))%mod;
	}
	printf("%lld",dp[n-1]);
	return 0;
}

Code passed after table printing:

//#include<bits/stdc++.h>
#include<iostream>
#include<vector>
#include<cstring>
#define LOCAL
using namespace std;
typedef long long ll;
//Long integers must be used here, because even if mod is an integer, overflow will occur as long as two numbers are multiplied

const ll maxn=1010;
const ll mod=1e9+7;
const ll maxa=1e5+10;
// int prm[70];int pn;
ll obs[maxn];
ll dp[maxn];
vector<int> facts[maxa];
int flag[maxa];

ll read(){
    ll s=0,f=1,c=getchar();
    while (c<'0' || c>'9' ) { if (c=='-') f=-1; c=getchar();}
    while (c>='0' && c<='9') {s=(s<<1)+(s<<3)+c-'0';c=getchar();}
    return f*s;
}
	
int main(){
    #ifdef LOCAL
    freopen("input.txt","r",stdin);
    #endif
    ll n=read();
    //Today, I finally saw the true face of typing tables: although it seems that the amount of data processed is large, this preprocessing avoids a lot of errors in the function later
    //Repetitive action
    for (int i=1;i<maxa;++i){
        for (int j=2*i;j<maxa;j+=i){
            facts[j].push_back(i);
        }
    }
    for (int i=0;i<n;++i){
    	obs[i]=read();
	}
    dp[0]=1;
	for (int i=1;i<n;++i){
        memset(flag,0,sizeof(flag));
		for (int j=i-1;j>=0;--j){
            int cont=0;
            ll dft=obs[i]-obs[j];
            int len=(int) facts[dft].size();
            for (int k=0;k<len;++k){
                if (!flag[facts[dft][k]]) {cont++;flag[facts[dft][k]]=1;}
            }
            flag[dft]=1;
			// dp[i]=(dp[i]+dp[j]*get_g(j,i)%mod)%mod;
            dp[i]=(dp[i]+dp[j]*cont%mod)%mod;
		}
		// dp[i]=(dp[i]+get_g(0,i))%mod;
	}
	printf("%lld",dp[n-1]);
	return 0;
}

Posted by hmvrulz on Tue, 30 Nov 2021 03:32:35 -0800