zoukankan      html  css  js  c++  java
  • 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
    ",ans+1);
    	}
    	return 0;
    }
    

    天才绅士少女助手克里斯蒂娜:

    就是推式子:

    $sumlimits_{i=l}^{r}sumlimits_{j=i+1}^{r}|v_i*v_j|^2=sumlimits_{i=l}^{r}sumlimits_{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=sumlimits_{i=l}^{r}(x_i^2*sumlimits_{j=i+1}^{r}y_j^2+y_i^2*sumlimits_{j=i+1}^{r}x_j^2+x_i*y_i*sumlimits_{j=i+1}^{r}x_j*y_j)$

    然后这个式子可以树状数组维护后面的sigma

    但是复杂度还是不优

    我们可以把i和j看成无序的,最后再除以2

    所以就有了:

    $sumlimits_{i=1}^{n}sumlimits_{j=i+1}^{n}|v_i*v_j|^2=sumlimits_{j=1}^{n}(x_j^2)*sumlimits_{j=1}^{n}(y_j^2)-sumlimits_{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
    ",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
    ",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;
    }
    
  • 相关阅读:
    清理disuz垃圾用户信息SQL语句
    解决C++代码单元测试中的难题不可验证和IO调用
    开源分布式平台mooon系统结构
    只显示指定网卡IP地址命令
    优秀开源杀毒软件ClamAV
    pyenv本地安装python
    TCP/IP学习笔记:ARP
    [linux] 如何在vim里面把空格缩进改为tab缩进
    TCP/IP学习笔记:ICMP
    TCP/IP学习笔记:UDP
  • 原文地址:https://www.cnblogs.com/Juve/p/11625208.html
Copyright © 2011-2022 走看看