csps-s模拟测试60嘟嘟噜,天才绅士少女助手克里斯蒂娜,凤凰院凶真题解
作者:互联网
题面:https://www.cnblogs.com/Juve/articles/11625190.html
嘟嘟噜:
约瑟夫问题
第一种递归的容易re,但复杂度较有保证
第二种适用与n大于m的情况
第三种O(n)用于n不太大或m大于n时
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define int long long #define re register using namespace std; int t,n,m; int calc(int n,int m){ if(n==1) return 0; if(n<m) return (calc(n-1,m)+m)%n; int s=calc(n-n/m,m)-n%m; return s<0?s+n:s+s/(m-1); } signed main(){ scanf("%lld",&t); while(t--){ scanf("%lld%lld",&n,&m); cout<<calc(n,m)+1<<endl; re int ans=0; int i=2; while(i<=n){ int tim=(i-ans-1)/m+1; if(i-1+tim>=n) tim=n-(i-1); i+=tim,ans=(ans+tim*m)%(i-1); } cout<<ans+1<<endl; ans=0; for(re int i=2;i<=n;++i){ ans=(ans+m)%i; } printf("%lld\n",ans+1); } return 0; }
天才绅士少女助手克里斯蒂娜:
就是推式子:
$\sum\limits_{i=l}^{r}\sum\limits_{j=i+1}^{r}|v_i*v_j|^2=\sum\limits_{i=l}^{r}\sum\limits_{j=i+1}^{r}(x_i^2*y_j^2+y_i^2*x_j^2-2*x_i*y_i*x_j*y_j)$
我们把所有$x_i^2$和$y_i^2$和$x_i*y_i$提出来,就有了
$ans=\sum\limits_{i=l}^{r}(x_i^2*\sum\limits_{j=i+1}^{r}y_j^2+y_i^2*\sum\limits_{j=i+1}^{r}x_j^2+x_i*y_i*\sum\limits_{j=i+1}^{r}x_j*y_j)$
然后这个式子可以树状数组维护后面的sigma
但是复杂度还是不优
我们可以把i和j看成无序的,最后再除以2
所以就有了:
$\sum\limits_{i=1}^{n}\sum\limits_{j=i+1}^{n}|v_i*v_j|^2=\sum\limits_{j=1}^{n}(x_j^2)*\sum\limits_{j=1}^{n}(y_j^2)-\sum\limits_{j=1}^{n}(x_j*y_j)^2$
然后就可以愉快地树状数组了
#include<iostream> #include<cstdio> #include<iostream> #include<algorithm> #define int long long #define re register using namespace std; const int MAXN=1e6+5; const int mod=20170927; int n,m; int read(){ int x=0;char ch=getchar(); while(ch<'0'||ch>'9') ch=getchar(); while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} return x; } struct node{ int x,y,s1,s2,s3; inline friend int operator * (node p,node q){ return ((p.x*q.y%mod-q.x*p.y%mod)%mod+mod)%mod; } }a[MAXN]; inline int lowbit(re int x){ return x&(-x); } struct BIT{ int c[MAXN]; inline void update(re int pos,re int val){ for(re int i=pos;i<=n;i+=lowbit(i)){ (c[i]+=val)%=mod; } } inline int query(re int pos){ re int res=0; for(re int i=pos;i>0;i-=lowbit(i)){ (res+=c[i])%=mod; } return res; } inline int ask(re int l,re int r){ return ((query(r)-query(l-1))%mod+mod)%mod; } }tr[3]; signed main(){ n=read(),m=read(); for(re int i=1;i<=n;++i){ a[i].x=read(),a[i].y=read(); a[i].s1=a[i].x*a[i].x%mod,a[i].s2=a[i].y*a[i].y%mod,a[i].s3=a[i].x*a[i].y%mod; tr[0].update(i,a[i].s1),tr[1].update(i,a[i].s2),tr[2].update(i,a[i].s3); } while(m--){ re int opt=read(); if(opt==1){ re int p=read(),x=read(),y=read(); tr[0].update(p,x*x%mod-a[p].s1); tr[1].update(p,y*y%mod-a[p].s2); tr[2].update(p,x*y%mod-a[p].s3); a[p]=(node){x%mod,y%mod,x*x%mod,y*y%mod,x*y%mod}; }else{ re int l=read(),r=read(),ans=0; ans=((tr[0].ask(l,r)*tr[1].ask(l,r)%mod-tr[2].ask(l,r)*tr[2].ask(l,r)%mod)%mod+mod)%mod; printf("%lld\n",ans); } } return 0; }
凤凰院凶真:
求两个数列的最长公共上升子序列并输出路径
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<stack> #define int long long using namespace std; const int MAXN=5005; int n,a[MAXN],m,b[MAXN],f[MAXN][MAXN],pre[MAXN][MAXN],pos=1; stack<int>sta; signed main(){ scanf("%lld",&n); for(int i=1;i<=n;++i) scanf("%lld",&a[i]); scanf("%lld",&m); for(int i=1;i<=m;++i) scanf("%lld",&b[i]); memset(pre,-1,sizeof(pre)); for(int i=1;i<=n;++i){ int v=0,k=0; for(int j=1;j<=m;++j){ f[i][j]=f[i-1][j]; if(b[j]<a[i]&&v<f[i-1][j]) v=f[i-1][j],k=j; if(a[i]==b[j]) f[i][j]=v+1,pre[i][j]=k; } } for(int i=1;i<=n;++i){ if(f[n][pos]<f[n][i]) pos=i; } printf("%lld\n",f[n][pos]); if(f[n][pos]!=0){ for(int i=n;i>=1;--i){ if(pre[i][pos]!=-1) sta.push(a[i]),pos=pre[i][pos]; } while(!sta.empty()){ printf("%lld ",sta.top()); sta.pop(); } puts(""); } return 0; }
标签:limits,int,题解,sum,院凶真,csps,re,MAXN,include 来源: https://www.cnblogs.com/Juve/p/11625208.html