2021.7.28考试总结[NOIP模拟26]
罕见的又改完了。
T1 神炎皇
吸取昨天三个出规律的教训,开场打完T2 20pts直接大力打表1h。
但怎么说呢,我不懂欧拉函数。(其实exgcd都忘了 于是只看出最大平方因子,不得不线性筛,爆拿60
正解又是看不懂的东西,取a和b的gcd d,把a,b同除d得到A,B,很容易想到(但好像不太容易证)A+B与AB互质。
那么要保证(A+B)d|ABd2,就要使(A+B)|d。又因为(A+B)d<n,所以(A+B)<根号n。
直接枚举A与B的和k,可以知道符合互质的AB数对有φ(k)对,d有n/k2对,相乘后累加即可。
code:
1 #include<bits/stdc++.h> 2 #define debug exit(0) 3 #define int long long 4 using namespace std; 5 const int NN=2e7+5; 6 int n,N,pri[NN],phi[NN],cnt,ans; 7 bool vis[NN]; 8 inline int read(){ 9 int x=0,f=1; 10 char ch=getchar(); 11 while(ch<'0'||ch>'9'){ 12 if(ch=='-') f=-1; 13 ch=getchar(); 14 } 15 while(ch>='0'&&ch<='9'){ 16 x=(x<<1)+(x<<3)+(ch^48); 17 ch=getchar(); 18 } 19 return x*f; 20 } 21 void write(int x){ 22 if(x<0) putchar('-'), x=-x; 23 if(x>9) write(x/10); 24 putchar(x%10+'0'); 25 } 26 void getphi(){ 27 phi[1]=1; 28 for(int i=2;i<=N;i++){ 29 if(!vis[i]) pri[++cnt]=i, phi[i]=i-1; 30 for(int j=1;j<=cnt&&pri[j]*i<=N;j++){ 31 int now=pri[j]*i; 32 vis[now]=1; 33 if(i%pri[j]) phi[now]=phi[i]*(pri[j]-1); 34 else{ phi[now]=phi[i]*pri[j]; break; } 35 } 36 } 37 } 38 signed main(){ 39 n=read(); N=sqrt(n); 40 getphi(); 41 for(int i=2;i<=N;i++) ans+=phi[i]*(n/(i*i)); 42 write(ans); putchar('\n'); 43 return 0; 44 }
T2 降雷皇
树状数组求最长上升子序列,中间维护方案数,如果同一位置有同样长度的方案,就把它们方案数累加。
用线段树也可。还能用双指针,因为fi相等的i电阻单调递减。
code:
1 #include<bits/stdc++.h> 2 #define debug exit(0) 3 using namespace std; 4 const int NN=1e5+5,p=123456789; 5 int n,type,maxr,r[NN],res; 6 struct node{ 7 int len,sum; 8 }s[NN]; 9 inline node max(node a,node b){ 10 if(a.len==b.len) 11 return (node){a.len,(a.sum+b.sum)%p}; 12 else return a.len>b.len?a:b; 13 } 14 inline int read(){ 15 int x=0,f=1; 16 char ch=getchar(); 17 while(ch<'0'||ch>'9'){ 18 if(ch=='-') f=-1; 19 ch=getchar(); 20 } 21 while(ch>='0'&&ch<='9'){ 22 x=(x<<1)+(x<<3)+(ch^48); 23 ch=getchar(); 24 } 25 return x*f; 26 } 27 void write(int x){ 28 if(x<0) putchar('-'), x=-x; 29 if(x>9) write(x/10); 30 putchar(x%10+'0'); 31 } 32 inline int lowbit(int x){ return x&(-x); } 33 inline void insert(int pos,node v){ 34 while(pos<=maxr){ 35 s[pos]=max(s[pos],v); 36 pos+=lowbit(pos); 37 } 38 } 39 inline node query(int pos){ 40 node res=(node){0,0}; 41 while(pos){ 42 res=max(res,s[pos]); 43 pos-=lowbit(pos); 44 } 45 return res; 46 } 47 void work(){ 48 for(int i=1;i<=n;i++){ 49 node nows=query(r[i]-1); 50 nows.len++; 51 if(nows.len==1) nows.sum++; 52 insert(r[i],nows); 53 } 54 node ans=query(maxr); 55 write(ans.len); putchar('\n'); 56 if(type) write(ans.sum), putchar('\n'); 57 } 58 signed main(){ 59 n=read(); type=read(); 60 for(int i=1;i<=n;i++) r[i]=read(), maxr=max(maxr,r[i]); 61 work(); 62 return 0; 63 }
T3 幻魔皇
树上全是菲波那契,再次在T3大力分类讨论。
考虑点对的LCA,LCA为点对中白点时可以直接用菲波那契求,根节点单算。
LCA为黑点时考虑黑点的两个子树,黑点的白色儿子单算。
预处理黑点为LCA,考虑最大深度为i中距离为j的点对fi,j,一波计算出解。
code:
1 #include<bits/stdc++.h> 2 #define debug exit(0) 3 #define int long long 4 using namespace std; 5 const int NN=5e3+5,p=123456789; 6 int n,fib[NN],ans[NN<<1],f[NN][NN<<1]; 7 inline int read(){ 8 int x=0,f=1; 9 char ch=getchar(); 10 while(ch<'0'||ch>'9'){ 11 if(ch=='-') f=-1; 12 ch=getchar(); 13 } 14 while(ch>='0'&&ch<='9'){ 15 x=(x<<1)+(x<<3)+(ch^48); 16 ch=getchar(); 17 } 18 return x*f; 19 } 20 void write(int x){ 21 if(x<0) putchar('-'), x=-x; 22 if(x>9) write(x/10); 23 putchar(x%10+'0'); 24 } 25 signed main(){ 26 n=read(); fib[1]=fib[2]=1; 27 for(int i=3;i<=n;i++) fib[i]=(fib[i-1]+fib[i-2])%p; 28 for(int i=2;i<=n;i++){ 29 for(int j=1;j<=n*2;j++) (f[i][j]+=f[i-1][j])%=p; 30 for(int j=3;j<=n;j++) (f[max(i,j)][i+j]+=fib[i-1]*fib[j-2]%p)%=p; 31 } 32 for(int i=2;i<=n;i++){ 33 for(int j=5;j<=2*(n-i);j++) (ans[j]+=fib[i-1]*f[n-i][j]%p)%=p; 34 for(int j=i+2;j<=n;j++) (ans[j-i+1]+=fib[i-1]*fib[j-i-1]%p)%=p; 35 for(int j=i+2;j<=n;j++) (ans[j-i]+=fib[j-i-1]*fib[i-2]%p)%=p; 36 } 37 for(int i=3;i<=n;i++) (ans[i-1]+=fib[i-2])%=p; 38 for(int i=1;i<=2*n;i++) 39 write(ans[i]), putchar(' '); putchar('\n'); 40 return 0; 41 }