T1 seq:
Sequence 2 (SEQ)
Description
Given a series {a} with a length of n, each element a_i in the initial sequence is no greater than 40. You can do it several times on it. In one operation, you will select the adjacent and equal two elements and merge them into an element with a new element value of \ ((old element value +1) \).
Would you please find out how a series of operations can make the maximum of the number of columns as large as possible? What is the maximum value?
Input
The first line of the input file is a positive integer n, which indicates the length of the sequence.
The next line of n is a positive integer not greater than 40, representing the sequence {a}.
Output
Outputs an integer that represents the maximum value in all possible sequences after any legal operation.
T1 is a DP, Luo gu P3147, original title link https://www.luogu.org/problemnew/show/P3147
Consider how to set the state, it is very strange that the initial value of the problem is not greater than 40, by the data range can be known, the final answer ans will not exceed max+logn, that is, the approximate maximum value of 58, then let us break through the thinking, the so-called answer to the state, that is set \ (f[ i][j]\) indicates that the answer of J can be merged from position I to the position of section \ (f[i][j]\) .
Initialization is \ (f[i][a[i]]\)=i;
Get state transfer equation \ (f[i][j]=f[i][f[i][j-1]][j-1]\)
It's very simple, and there's one more point to note that every time J is introduced by J-1, you have to enumerate J first.
Although I do not understand the meaning of eolv, but this should be a DP of the attention of the place, or to remember.
#include<iostream>#include<cstdio>using namespace std;inline int read(){ int sum=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-')f=-1; ch=getchar(); } while(ch>='0'&&ch<='9'){ sum=(sum<<1)+(sum<<3)+ch-'0'; ch=getchar(); } return sum*f;}const int wx=262144;int f[wx][59];int n,ans;int x;int main(){ freopen("seq.in","r",stdin); freopen("seq.out","w",stdout); n=read(); for(int i=1;i<=n;i++){ x=read(); f[i][x]=i+1; } for(int j=2;j<=58;j++){ for(int i=1;i<=n;i++){ if(!f[i][j])f[i][j]=f[f[i][j-1]][j-1]; if(f[i][j])ans=max(ans,j); } } printf("%d\n",ans); fclose(stdin); fclose(stdout); return 0;}
T2:sum
Play the table good question Ah, eolv big guy to talk about this problem when summed up the law:
In the question of math: there are several important functions that should be first thought:
1) d (n) indicates the number of constraints on N.
2) Phi (n) represents the number of n coprime that are less than or equal to N. (Euler function)
3) u (n) indicates the distribution of the factors of N. (Möbius function)
4) The ID (n) means n itself. (Nonsense, the table of course to Output n AH).
This problem in the examination room to find the law for one hours (too food ... , finally really can not find out for 10,000 times the data range of inquiry 1e9 of the practice, lashing disturbed prophecymusic hit a 70-point approach, did not think incredibly a, thanks to data thanks to the data.
(Oies Dafa is good!!! )
Eolv after said suddenly feel this question is quite simple, very good card, then come to pass it again.
For f (N)
\ (f (n) =n^2-\sum_{a=1,a<=n}\sum_{b=1,b<=n}[n|ab]\)
? =\ (N^2-\SUM_{A=1,A<=N}\SUM_{B=1,B<=N}[N/GCD (a,n) |a*b/gcd (a,n)]\)
? =\ (N^2-\SUM_{A=1,A<=N}\SUM_{B=1,B<=N}[N/GCD (a,n) |b]\)//Because at this time N/GCD (a,n) and A/GCD (a,n) are coprime, so A/GCD (a , n) No contribution to the answer
? =\ (n^2-\sum_{a=1,a<=n}gcd (a,n) \)//This is a difficult step to understand, considering that the value range of B is 1 to n so the above means that the number of numbers belonging to 1 to N and divisible n/gcd (a,n), then the natural is n /N/GCD (a,n) =GCD (a,n).
? =\ (N^2-\sum_{d|n}phi (n/d) *d\)//A very common step in the proof of number theory, enumeration factor
for G (N), we bring F (d) into
\ (g (n) =\sum_{d|n}f (d) \)
? =\ (\sum_{d|n}d^2-\sum_{d|n}\sum_{p|d}phi (d/p) *p\)
? =\ (\sum_{d|n}d^2-\sum_{d|n} (Phi (d) *id (d)) \)/// (\sum\) can be considered as the Dirichlet convolution of the PHI function and the ID function
? =\ (\sum_{d|n}d^2-\sum_{d|n}1 (n/d) * ((Phi (d) *id (d) ))
? =\ (\sum_{d|n}d^2-1 (n) *phi (n) *id (n) \)
? =\ (\sum_{d|n}d^2-id (n) *id (n) \)
? =\ (\sum_{d|n}d^2-\sum_{d|n}n* (n/d) \)
? =\ (\sum_{d|n}d^2-\sum_{d|n}n\)
It is easy to conclude that the sum of the squares of the n factor and the approximate number of n*n are subtracted.
#include<iostream>#include<cstdio>#define ll long longusing namespace std;ll g[2005];int t;ll n,ans;ll work(ll now){ ll re=0;//记录因子的平方和 ll tmp=0;//记录因子个数 for(int i=1;i*i<=now;i++){ if((now%i==0)&&(i*i!=now)){ re+=i*i;re+=(now/i)*(now/i); tmp+=2; } else if(i*i==now){ re+=i*i; tmp++; } } return re-now*tmp;}int main(){ freopen("sum.in","r",stdin); freopen("sum.out","w",stdout); scanf("%d",&t); while(t--){ scanf("%lld",&n); ans=work(n); printf("%lld\n",ans); } fclose(stdin); fclose(stdout); return 0;}
T3:frame
Description
You want to give Makik a Valentine's Day present, but only a piece of paper in the hand. This piece of paper can be thought of as a rectangle made of H-line W Lege, which, unfortunately, has been damaged by even some of the squares. To make this tattered piece of paper look like a gift, you cut out a box with a side length of not less than L, and the damaged lattice cannot be included in the box. Here, a square with a side length of S (s≥3) refers to the shape of a lattice of the outermost 4 (s-1) of the square with the size of SxS.
Before you cut the grid paper, please calculate how many different boxes can be cut out altogether?
Input
The first line of the input file contains four integers h,w,l,p the total number of rows in the grid, the number of columns, the minimum limit for the length of the box, and the number of damaged squares.
The next P line, where line I contains two integers x_i, y_i, indicates that the grid on the Y_i column of the x_i row is damaged.
Output
Outputs a single integer representing the number of schemes to cut out different squares.
Data size and conventions
For 20% of data, H \ (\leq\) , w$\leq$500
For another 20% of the data, P = 0.
For another 20% of the data, 1 \ (\leq\) P\ (\leq\) 10.
For 100% data, 1 \ (\leq\) h$\leq$4000, 1 \ (\leq\) W \ (\leq\) 4000, 3 \ (\leq\) L \ (\leq \) min{w, H}, 0 \ (\leq\) P \ (\leq\) 100000 1≤h≤4000,1≤w≤4000,3≤l≤min{w,h},0≤p≤100000.
Which is very simple is the partial p=0, the direct output does not explain
\[\sum_{i=l}^{i<=min (N,m)} (n-i+1) * (m-i+1) \]
And the previous data range is smaller than the 20 points of direct violence, I wrote \ (n^4\), the big guys are prefixed and optimized to the \ (n^3\), well, lower than they are very not a loss.
Here is a positive solution, thanks to GMPOTLC, careful explanation.
Because the question is the number of squares, then consider the nature of the square, it is easy to think of the square of the upper left corner of the point and the lower right corner of the point is on the same main diagonal, then you can use the main diagonal as our intermediate variable to enumerate, and then find each main diagonal on the number of valid squares, the total take one and
To enumerate the diagonal actions:
for(int x=n,y=1;y<=m;x==1?++y:--x){//可以说是非常秀了 int len=0; memset(sum,0,sizeof sum); memset(edge,0,sizeof edge); memset(head,0,sizeof head);//每次拉出一条主对角线都是一次新的区间XJB操作,所以每次都要初始化 num=0; for(int i=x,j=y;i<=n&&j<=m;i++,j++)len++;//当前是拉出一条主对角线 。。。 。。。 }
So consider how to count the legal squares on each diagonal, and the brute force enumeration is definitely not possible.
And because it is a sum, consider using our familiar data structure to maintain, and because for each point, let it as a square of the upper left corner point, then the corresponding legal right bottom corner is in a range, so it is easy to think of the tree-like array maintenance and, because of the difference.
Consider the current enumeration to the first J point of the diagonal, which is mainly three operations:
One, we enumerate to this point, can be as a square in the lower right corner of the position, so here to statistics the answer.
1) First we want to update this point as the bottom right corner will have how many left the upper corner corresponding to it, then we need to record this point in advance as the lower right corner of the legal upper left corner. Because the upper left corner must be enumerated first, so we can find the interval of the right lower corner of the point that we enumerate to as the upper-left corner, and modify the interval by the difference. But here is the delay tag, that is, only when we enumerate to its corresponding bottom right corner of the beginning of the position, this point has the answer, so this is only updated.
Perhaps the above words are not clear enough, but try to understand them as much as possible.
The specific operation is that we record this point in advance as the lower right corner of the upper-left corner of the point, that is, from the lower right corner to a top-left corner, when not seen in the lower right corner, return to the upper left corner of the position to start adding 1.
Because this point is either the upper-left or the lower-right corner, there will be a corresponding legal interval, so it is possible to modify the interval by the tree array difference.
for(int j=head[i];j;j=edge[j].nxt){ int v=edge[j].to; update(v,edge[j].dis); }
2) has updated the current tree array prefix and, then we have to know the current point as the lower right corner corresponding to the upper left corner of the legal interval, so the direct interval query can be.
if(f2[i+x-1][i+y-1] >= l)ans+=query(i-l+1)-query(i-f2[i+x-1][i+y-1]);
3) The point you are currently enumerating to is of course not only as the lower right corner of the operation. So what should be done now as the upper-left corner?
Front in 1) The operation is already mentioned, we need to deal with the current point as the upper left corner corresponding to a valid lower right corner of the interval, mark the beginning and end of the interval, but when we enumerate to these two positions, we can return to change the point to the answer of the contribution, that is, a difference.
So find these two points, by looking at the current point from these two points to complete the processing of information (can also become the implementation of the tag).
Eolv the big guy to maintain a list at each point, but after the teachings of the GMPOTLC, I was in this part through the chain forward to the star to achieve.
The above difficulty is finished, there is still one detail, we need to pre-preprocess each point up to the left up or down up to the maximum length of the extension. Then the legal interval of the other point on the diagonal of each point is the one at the end of the L decision given in the question, and at one end it is determined by the limit length just mentioned.
Then you have to judge the validity of the interval corresponding to each point.
That is, if the left endpoint of an interval is greater than or equal to the right end point, then it is certainly not possible.
Code
#include <iostream> #include <cstdio> #include <cstring>using namespace std;typedef long Long ll;const int Wx=4001;inline int read () {int sum=0,f=1; Char Ch=getchar (); while (ch< ' 0 ' | | Ch> ' 9 ') {if (ch== '-') f=-1; Ch=getchar (); } while (ch>= ' 0 ' &&ch<= ' 9 ') {sum= (sum<<1) + (sum<<3) +ch-' 0 '; Ch=getchar (); } return sum*f;} struct node{int x, y;} a[wx];struct e{int Nxt,to,dis;} Edge[wx*2];long Long Ans;int Head[wx],sum[wx],vis[wx][wx],left[wx][wx],right[wx][wx],up[wx][wx],down[wx][wx];int F1[wx][wx],f2[wx][wx];int n,m,p,l,x,y,z,num,tot;void Add (int from,int to,int dis) {Edge[++num].nxt=head[from]; Edge[num].to=to; Edge[num].dis=dis; Head[from]=num;} void Update (int pos,ll k) {for (int i=pos;i<=n;i+= (i&-i)) {sum[i]+=k; }}LL query (int x) {ll re=0; for (int i=x;i>=1;i-= (i&-i)) {re+=sum[i]; } return re;} void Pre () {for (int. i=1;i<=n;i++) {for (int j=1;j<=m;j++) {if (!vis[i][j]) {left[i][j]=left[i][j-1]+1; up[i][j]=up[i-1][j]+1; }}} for (int i=n;i>=1;i--) {for (int j=m;j>=1;j--) {if (!vis[i][j]) {Ri ght[i][j]=right[i][j+1]+1; down[i][j]=down[i+1][j]+1; }}} for (int i=1;i<=n;i++) {for (int j=1;j<=m;j++) {f1[i][j]=min (right[i][j],down[i][ j]);//ability to extend to the right below F2[i][j]=min (Left[i][j],up[i][j]);//ability to extend the length of the upper left}}}int main () {Freopen ("frame . In "," R ", stdin); Freopen ("Frame.out", "w", stdout); N=read (); M=read (); L=read ();p =read (); for (int i=1;i<=p;i++) {x=read (); Y=read (); vis[x][y]=1; } pre (); for (int x=n,y=1;y<=m;x==1?++y:--x) {int len=0; memset (sum,0,sizeof sum); memset (edge,0,sizeof edge); memset (head,0,sizeof head); num=0; for (int i=x,j=y;i<=n&&j<=m;i++,j++) len++;is currently pulling out a main diagonal for (int i=1;i<=len;i++) {for (int j=head[i];j;j=edge[j].nxt) {int V=edge [J].to; Update (V,EDGE[J].DIS); } if (F2[i+x-1][i+y-1] >= l) ans+=query (i-l+1)-query (i-f2[i+x-1][i+y-1]); if (F1[i+x-1][i+y-1] >= l) Add (i+l-1,i,1); if (F1[i+x-1][i+y-1] >= l) Add (i+f1[i+x-1][i+y-1],i,-1); }} printf ("%lld\n", ans); return 0;}
Specific details or a lot of, to understand well.
10-2 National Day Fifth simulation game