zoukankan      html  css  js  c++  java
  • XVII Open Cup named after E.V. Pankratiev. Eastern GP, Division 1

    A. Count The Ones

    $ans=b-c+1$。

    #include <stdio.h>
    using namespace std ;
    
    int a  , b , c ;
    
    void solve () {
    	printf ( "%d
    " , 1 + b - c ) ;
    }
    
    int main () {
    	while ( ~scanf ( "%d%d%d" , &a , &b , &c ) ) solve () ;
    	return 0 ;
    }
    

      

    B. Craters

    求出凸包,然后枚举凸包上两个点,对第三个点旋转卡壳。因为随机数据凸包期望点数为$O(sqrt{n})$,故时间复杂度为$O(nlog n)$。

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<set>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int>PI;
    const int N=200010;
    int n,m,_,i,j,k,x,y;
    set<PI>T;
    ll ans=-1;
    struct P{
      int x,y;
      P(){}
      P(int _x,int _y){x=_x,y=_y;}
      P operator-(P b){return P(x-b.x,y-b.y);}
      bool operator<(const P&p)const{
        if(x!=p.x)return x<p.x;
        return y<p.y;
      }
      void write(){
        printf("%d %d
    ",x,y);
      }
    }a[N],b[N<<1],ans0,ans1,ans2;
    inline ll cross(P a,P b){
      return 1LL*a.x*b.y-1LL*a.y*b.x;
    }
    inline ll vect(P p,P p1,P p2){
      return 1LL*(p1.x-p.x)*(p2.y-p.y)-1LL*(p1.y-p.y)*(p2.x-p.x);
    }
    int convexhull(P*p,int n,P*q){
      int i,k,m;
      sort(p,p+n);
      m=0;
      for(i=0;i<n;q[m++]=p[i++])while(m>1&&vect(q[m-2],q[m-1],p[i])<=0)m--;
      k=m;
      for(i=n-2;i>=0;q[m++]=p[i--])while(m>k&&vect(q[m-2],q[m-1],p[i])<=0)m--;
      return --m;
    }
    inline void work(P a,P b,P c){
      ll now=cross(a,b)+cross(b,c)+cross(c,a);
      if(now<0)now=-now;
      if(now>ans)ans=now,ans0=a,ans1=b,ans2=c;
    }
    inline ll area(P a,P b,P c){
      ll now=cross(a,b)+cross(b,c)+cross(c,a);
      if(now<0)now=-now;
      return now;
    }
    int main(){
      scanf("%d",&n);
      if(n<200){
        for(i=0;i<n;i++)scanf("%d%d",&a[i].x,&a[i].y);
        for(i=0;i<n;i++)for(j=0;j<i;j++)for(k=0;k<j;k++){
          work(a[i],a[j],a[k]);
        }
        ans0.write();
        ans1.write();
        ans2.write();
        return 0;
      }
      _=n;
      n=0;
      while(_--){
        scanf("%d%d",&x,&y);
        if(T.find(PI(x,y))!=T.end())continue;
        a[n++]=P(x,y);
        T.insert(PI(x,y));
      }
      m=convexhull(a,n,b);
      for(i=0;i<m;i++)b[i+m]=b[i];
      for(i=0;i<m;i++){
        for(j=i+1,k=j+1;j<i+m;j++){
          if(k<=j)k=j+1;
          while(k+1<i+m&&area(b[i],b[j],b[k])<=area(b[i],b[j],b[k+1]))k++;
          work(b[i],b[j],b[k]);
        }
      }
      ans0.write();
      ans1.write();
      ans2.write();
    }
    

      

    C. MSTrikes back!

    记录最后$5$个点连通性的最小表示然后DP,注意到边权的周期不会太大,所以可以直接跳过完整的周期。

    #include<stdio.h>
    #include<algorithm>
    #include<math.h>
    #include<string.h>
    #include<string>
    #include<vector>
    #include<set>
    #include<map>
    #include<queue>
    #include<time.h>
    #include<assert.h>
    #include<iostream>
    using namespace std;
    typedef long long LL;
    typedef pair<int,int>pi;
    const int Ms=3125;
    const LL Inf=1LL<<60;
    const int LIM=100;
    int n,seed;
    LL in[LIM+1];
    LL f[LIM+1][Ms];
    LL dp[2][Ms];
    void init(int cs,LL val){
    	for(int i=0;i<Ms;i++)dp[cs][i]=val;
    }
    int g[Ms][(1<<5)+1];
    void decode(int mask,int *a){
    	for(int i=0;i<5;i++){
    		a[i]=mask%5;
    		mask/=5;
    	}
    }
    void zuixiao(int *a){
    	int dui[10];
    	memset(dui,-1,sizeof dui);
    	int cur=0;
    	for(int i=0;i<5;i++){
    		int x=a[i];
    		if(dui[x]<0){
    			dui[x]=cur++;
    		}
    		a[i]=dui[x];
    	}
    }
    int encode(int *a){
    	int res=0,tmp=1;
    	for(int i=0;i<5;i++,tmp=tmp*5){
    		res+=a[i]*tmp;
    	}
    	return res;
    }
    bool testt(int *a){
    	int b[10];
    	for(int i=0;i<5;i++)b[i]=a[i];
    	zuixiao(b);
    	for(int i=0;i<5;i++)if(b[i]!=a[i])return 0;
    	return 1;
    }
    void pre(){
    	int a[10],b[10];
    	for(int mask=0;mask<Ms;mask++){
    		decode(mask,a);
    		if(!testt(a)){
    			for(int j=0;j<1<<5;j++)g[mask][j]=-1;
    			continue;
    		}
    		//for(int i=0;i<5;i++)printf("%d ",a[i]);puts(":
    ");
    		for(int j=0;j<1<<5;j++){
    			for(int i=0;i<5;i++)b[i]=a[i];
    			b[5]=6;
    			for(int k=0;k<5;k++){
    				if(j>>k&1){
    					for(int t=0;t<5;t++){
    						if(t==k)continue;
    						if(b[t]==b[k])b[t]=b[5];
    					}
    					b[k]=b[5];
    				}
    			}
    			bool flag=0;
    			for(int k=1;k<=5;k++)if(b[0]==b[k]){flag=1;break;}
    			if(!flag)g[mask][j]=-1;
    			else{
    				for(int k=0;k<5;k++)b[k]=b[k+1];
    				zuixiao(b);
    				//for(int k=0;k<5;k++)printf("%d ",b[k]);puts("");
    				g[mask][j]=encode(b);
    			}
    		}
    	}
    }
    void upd(LL &x,LL y){if(x>y)x=y;}
    int main(){
    	pre();
    	int _;scanf("%d",&_);
    	while(_--){
    		scanf("%d%d",&n,&seed);
    		int cs=0;
    		init(cs,Inf);
    		dp[cs][0]=0;
    		for(int i=2;i<=n&&i<=LIM;i++){
    			init(cs^1,Inf);
    			seed=seed*907%2333333;
    			LL bq[10];
    			int T=seed;
    			in[i]=T;
    			for(int j=0;j<5;j++){
    				if(i-(5-j)<1)bq[j]=Inf;
    				else {
    					seed=seed*907%2333333;
    					bq[j]=seed^T;
    				}
    			}
    			for(int mask=0;mask<Ms;mask++){
    				LL w=dp[cs][mask];
    				if(w==Inf)continue;
    				for(int j=0;j<1<<5;j++){
    					if(g[mask][j]<0)continue;
    					bool flag=1;
    					for(int k=0;k<5;k++)if((j>>k&1)&&(bq[k]==Inf)){
    						flag=0;continue;
    					}
    					if(!flag)continue;
    					LL nw=w;
    					for(int k=0;k<5;k++){
    						if(j>>k&1)nw+=bq[k];
    					}
    					upd(dp[cs^1][g[mask][j]],nw);
    				}
    			}
    			cs^=1;
    			for(int j=0;j<Ms;j++)f[i][j]=dp[cs][j];
    		}
    		if(n<=LIM)printf("%lld
    ",dp[cs][0]);
    		else{
    			LL pace,pacew;
    			for(int i=LIM-1;;i--)if(in[i]==in[LIM]){
    				pace=LIM-i;
    				break;
    			}
    			int st=(n-LIM)/pace*pace+LIM;
    			//printf("st=%d
    ",st);
    			for(int i=0;i<Ms;i++){
    				dp[cs][i]=f[LIM][i]+1LL*(n-LIM)/pace*(f[LIM][i]-f[LIM-pace][i]);
    			}
    			for(int i=st+1;i<=n;i++){
    				init(cs^1,Inf);
    				seed=seed*907%2333333;
    				LL bq[10];
    				int T=seed;
    				for(int j=0;j<5;j++){
    					if(i-(5-j)<1)bq[j]=Inf;
    					else {
    						seed=seed*907%2333333;
    						bq[j]=seed^T;
    					}
    				}
    				for(int mask=0;mask<Ms;mask++){
    					LL w=dp[cs][mask];
    					if(w==Inf)continue;
    					for(int j=0;j<1<<5;j++){
    						if(g[mask][j]<0)continue;
    						bool flag=1;
    						for(int k=0;k<5;k++)if((j>>k&1)&&(bq[k]==Inf)){
    							flag=0;continue;
    						}
    						if(!flag)continue;
    						LL nw=w;
    						for(int k=0;k<5;k++){
    							if(j>>k&1)nw+=bq[k];
    						}
    						upd(dp[cs^1][g[mask][j]],nw);
    					}
    				}
    				cs^=1;
    			}
    			printf("%lld
    ",dp[cs][0]);
    		}
    	}	
    	return 0;
    }
    

      

    D. Skyscrapers

    首先用set维护所有已经被摧毁的建筑。然后用线段树维护区间内最容易被向左/向右的冲击波击毁的建筑即可。时间复杂度$O(nlog n)$。

    #include<cstdio>
    #include<set>
    #include<algorithm>
    using namespace std;
    const int N=100010,M=262150;
    int n,m,i,x,ans,f[N],g[N];
    set<int>T;
    int vl[M],vr[M],pos[N],p;
    inline int mergel(int x,int y){
      if(!x||!y)return x+y;
      return f[x]>f[y]?x:y;
    }
    inline int merger(int x,int y){
      if(!x||!y)return x+y;
      return g[x]<g[y]?x:y;
    }
    void build(int x,int a,int b){
      if(a==b){
        pos[a]=x;
        vl[x]=vr[x]=a;
        return;
      }
      int mid=(a+b)>>1;
      build(x<<1,a,mid);
      build(x<<1|1,mid+1,b);
      vl[x]=mergel(vl[x<<1],vl[x<<1|1]);
      vr[x]=merger(vr[x<<1],vr[x<<1|1]);
    }
    void askl(int x,int a,int b,int c,int d){
      if(c<=a&&b<=d){
        p=mergel(p,vl[x]);
        return;
      }
      int mid=(a+b)>>1;
      if(c<=mid)askl(x<<1,a,mid,c,d);
      if(d>mid)askl(x<<1|1,mid+1,b,c,d);
    }
    void askr(int x,int a,int b,int c,int d){
      if(c<=a&&b<=d){
        p=merger(p,vr[x]);
        return;
      }
      int mid=(a+b)>>1;
      if(c<=mid)askr(x<<1,a,mid,c,d);
      if(d>mid)askr(x<<1|1,mid+1,b,c,d);
    }
    inline void kill(int x){
      ans++;
      T.insert(x);
      x=pos[x];
      vl[x]=vr[x]=0;
      for(x>>=1;x;x>>=1){
        vl[x]=mergel(vl[x<<1],vl[x<<1|1]);
        vr[x]=merger(vr[x<<1],vr[x<<1|1]);
      }
    }
    inline void workl(int l,int r,int t){
      if(l>r)return;
      while(1){
        p=0;
        askl(1,1,n,l,r);
        if(!p)return;
        if(f[p]<t)return;
        kill(p);
      }
    }
    inline void workr(int l,int r,int t){
      if(l>r)return;
      while(1){
        p=0;
        askr(1,1,n,l,r);
        if(!p)return;
        if(g[p]>t)return;
        kill(p);
      }
    }
    int main(){
      scanf("%d",&n);
      for(i=1;i<=n;i++)scanf("%d",&x),f[i]=i-x,g[i]=i+x;
      T.insert(0);
      T.insert(n+1);
      build(1,1,n);
      scanf("%d",&m);
      while(m--){
        scanf("%d",&x);
        ans=0;
        kill(x);
        set<int>::iterator j=T.find(x),k;
        k=j;
        j--;k++;
        workl(*j+1,x-1,f[x]);
        workr(x+1,*k-1,g[x]);
        printf("%d
    ",ans);
      }
    /*
    left:
    a[x]-a[y]>=x-y
    y-a[y]>=x-a[x]
    get max(y-a[y])
    right:
    a[x]-a[y]>=y-x
    y+a[y]<=x+a[x]
    get min(y+a[y])
    */
    }
    

      

    E. Blackboard

    按题意模拟即可。

    #include<stdio.h>
    #include<algorithm>
    #include<math.h>
    #include<string.h>
    #include<string>
    #include<vector>
    #include<set>
    #include<map>
    #include<queue>
    #include<time.h>
    #include<assert.h>
    #include<iostream>
    using namespace std;
    typedef long long LL;
    typedef pair<int,int>pi;
    int n,ty;
    int a[103][103];
    void rev(){
    	for(int i=1;i<=n;i++){
    		for(int j=i;j<=n;j++){
    			swap(a[i][j],a[j][i]);
    		}
    	}
    }
    void solve1(){
    	int cur=1;
    	for(int i=1;i<=n;i++){
    		if(i&1){
    			for(int j=1;j<=n;j++){
    				a[i][j]=cur++;
    			}
    		}
    		else{
    			for(int j=n;j>=1;j--){
    				a[i][j]=cur++;
    			}
    		}
    	}
    }
    bool isok(int x,int y){
    	return x>=1&&x<=n&&y>=1&&y<=n&&a[x][y]==0;
    }
    int di[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
    void solve2(){
    	int d=0;
    	int sx=1,sy=1;
    	memset(a,0,sizeof a);
    	int cur=1;
    	for(int it=1;it<=n*n;it++){
    		a[sx][sy]=cur++;
    		int nx=sx+di[d][0],ny=sy+di[d][1];
    		if(it==n*n)break;
    		while(!isok(nx,ny)){
    			d++;
    			d%=4;
    			nx=sx+di[d][0],ny=sy+di[d][1];
    		}
    		sx=nx,sy=ny;
    	}
    }
    int main(){
    	while(scanf("%d%d",&n,&ty)!=EOF){
    		if(ty==1||ty==2)solve1();
    		if(ty==3||ty==4)solve2();
    		if(ty==2||ty==4)rev();
    		for(int i=1;i<=n;i++){
    			for(int j=1;j<=n;j++){
    				printf("%d%c",a[i][j],j==n?'
    ':' ');
    			}
    		}
    	}
    	return 0;
    }
    

      

    F. Buddy Numbers

    若质数太多那么显然无解,对于小数据爆搜即可。

    #include <bits/stdc++.h>
    using namespace std ;
    
    int a[1000] , n ;
    
    void solve () {
    	if ( n == 1 ) {
    		printf ( "1
    " ) ;
    		return ;
    	}
    	if ( n == 2 ) {
    		printf ( "1 2
    " ) ;
    		return ;
    	}
    	if ( n == 3 ) {
    		printf ( "2 1 3
    " ) ;
    		return ;
    	}
    	if ( n == 4 ) {
    		printf ( "2 4 1 3
    " ) ;
    		return ;
    	}
    	if ( n == 6 ) {
    		printf ( "3 6 2 4 1 5
    " ) ;
    		return ;
    	}
    	printf ( "-1
    " ) ;
    		
    }
    
    int main () {
    	while ( ~scanf ( "%d" , &n ) ) solve () ;
    	return 0 ;
    }
    

      

    G. Gmoogle

    按题意模拟即可。注意首尾空格的处理以及文末没有标点符号的情况的处理。

    #include<stdio.h>
    #include<algorithm>
    #include<math.h>
    #include<string.h>
    #include<string>
    #include<vector>
    #include<set>
    #include<map>
    #include<queue>
    #include<time.h>
    #include<assert.h>
    #include<sstream>
    #include<iostream>
    using namespace std;
    typedef long long LL;
    typedef pair<int,int>pi;
    string s;
    vector<string>jz;
    int can[1020];
    int isend(int loc){
    	if(s[loc]!='.'&&s[loc]!='!'&&s[loc]!='?')return 0;
    	if(s[loc]=='.'){
    		int j=loc+1;
    		while(j<s.size()&&s[j]==' ')j++;
    		if(j<s.size()&&s[j]>='a'&&s[j]<='z')return 0;
    	}
    	return 1;
    }
    void cg(char &c){if(c>='A'&&c<='Z')c=c-'A'+'a';}
    bool cmp(char c1,char c2){
    	cg(c1),cg(c2);
    	if(c1==c2)return 1;
    	return 0;
    }
    bool ok(string &wb,string& in){
    	for(int i=0;i+in.size()<=wb.size();i++)if(isalpha(wb[i])){
    		bool flag=1;
    		if(i&&isalpha(wb[i-1]))continue;//
    		int j=i+in.size();
    		if(j<wb.size()&&isalpha(wb[j]))continue;//
    		//while ( j < wb.size () && wb[j] == ' ' ) ++ j ;
    		//if(j<wb.size()-1&&wb[j]=='.')continue;
    		for(int j=0;j<in.size();j++){
    			if(cmp(wb[i+j],in[j])!=1){flag=0;break;}
    		}
    		if(flag)return 1;
    	}
    	return 0;
    }
    bool zhu(char x){
      if(x>='a'&&x<='z')return 1;
      if(x>='A'&&x<='Z')return 1;
      if(x==' ')return 1;
      if(x>='0'&&x<='9')return 1;
      if(x=='.'||x=='?'||x=='!')return 1;
      return 0;
    }
    void fix ( string& s ) {
    	while ( !zhu(s[s.size () - 1]) ) s.pop_back () ;
    }
    int main(){
    	getline(cin,s);
    	fix ( s ) ;
    	int k = 0 ;
    	for(int l=0;l<s.size();){
    		while(l<s.size()&&s[l]==' ')l++;
    		if(l>=s.size())break;
    		//if ( s[l] == '.' /*|| s[l] == '?' || s[k] == '!'*/ ) while ( 1 ) ;
    		int r=l;
    		string tmp="";
    		while(r<s.size()&&!isend(r))tmp.push_back(s[r++]);
    		if ( r < s.size () ) tmp.push_back(s[r++]);
    		while(tmp[tmp.size()-1]==' ')tmp.pop_back();
    		//printf ( "%d
    " , ( int ) tmp.size () ) ;
    		jz.push_back(tmp);
    		l=r;
    	}
    	/*
    	cout<<"OUTPUT"<<endl;
    	for(int i=0;i<jz.size();i++)cout<<jz[i]<<endl;
    	*/
    	int q;scanf("%d",&q);
    	string rub;
    	getline(cin,rub);
    	while(q--){
    		string que;
    		getline(cin,que);
    		fix ( que ) ;
    		for(int i=0;i<jz.size();i++)can[i]=1;
    		stringstream ss(que);
    		string tmp;
    		while(ss>>tmp){
    			fix ( tmp ) ;
    			for(int i=0;i<jz.size();i++){
    				if(!ok(jz[i],tmp))can[i]=0;
    			}
    		}
    		int i=0,j=que.size()-1;
    		while(que[i]==' ')i++;
    		while(que[j]==' ')j--;
    		cout<<"Search results for "";
    		for(int it=i;it<=j;it++)printf("%c",que[it]);
    		cout<<"":
    ";
    		for(int i=0;i<jz.size();i++)if(can[i]){
    			cout<<"- ""<<jz[i]<<""
    ";
    		}
    	}
    	return 0;
    }
    

      

    H. Generator

    线性筛求出每个数的最小质因子即可。

    #include<stdio.h>
    #include<algorithm>
    #include<math.h>
    #include<string.h>
    #include<string>
    #include<vector>
    #include<set>
    #include<map>
    #include<queue>
    #include<time.h>
    #include<assert.h>
    #include<iostream>
    using namespace std;
    typedef long long LL;
    typedef pair<int,int>pi;
    LL n;
    LL sum[10000020];
    int tot[10000020];
    bool isp[10000200];
    vector<int>pri;
    const int Maxn=10000010;
    int getsq(int x){
    	int tmp=sqrt(x+0.5);
    	while(tmp*tmp<x)tmp++;
    	while(tmp*tmp>x)tmp--;
    	return tmp-1;
    }
    void pre(){
    	for(int i=2;i<Maxn;i++){
    		if(!isp[i])pri.push_back(i),sum[i]=getsq(i);
    		for(int j=0;j<pri.size();j++){
    			int x=pri[j];
    			if(x*i>=Maxn)break;
    			sum[x*i]=x-1;
    			isp[i*x]=1;
    			if(i%x==0)break;
    		}
    	}
    	//for(int i=2;i<=10;i++)printf("%lld ",sum[i]);puts("");
    	for(int i=2;i<Maxn;i++)sum[i]+=sum[i-1];
    	for(int i=2;i<Maxn;i++)tot[i]=tot[i-1]+(!isp[i]);
    }
    int main(){
    	pre();
    	int _;scanf("%d",&_);
    	while(_--){
    		scanf("%lld",&n);
    		LL ans=sum[n];
    		if(ans==0)printf("0/1
    ");
    		else{
    			LL gc=__gcd((LL)tot[n],ans);
    			printf("%lld/%lld
    ",ans/gc,tot[n]/gc);
    		}		
    	}
    	return 0;
    }
    

      

    I. Addition

    维护二进制字典树即可。

    #include <bits/stdc++.h>
    using namespace std ;
    
    typedef long long LL ;
    
    const int MAXN = 100005 ;
    
    int nxt[MAXN][2] ;
    int cnt[MAXN] ;
    char s[MAXN] , s1[MAXN] ;
    int cur , root ;
    int n , m ;
    
    int newnode () {
    	++ cur ;
    	nxt[cur][0] = nxt[cur][1] = 0 ;
    	cnt[cur] = 0 ;
    	return cur ;
    }
    
    void insert ( char s[] ) {
    	int now = root ;
    	for ( int i = 0 ; i < m ; ++ i ) {
    		int x = s[i] ;
    		if ( !nxt[now][x] ) nxt[now][x] = newnode () ;
    		now = nxt[now][x] ;
    		cnt[now] ++ ;
    	}
    }
    
    int query ( char s[] ) {
    	int now = root , ans = 0 ;
    	for ( int i = 0 ; i < m ; ++ i ) {
    		int x = s[i] ;
    		if ( !x ) ans += cnt[nxt[now][1]] ;
    		now = nxt[now][x] ;
    	}
    	return ans ;
    }
    
    void solve () {
    	cur = 0 ;
    	root = newnode () ;
    	for ( int i = 1 ; i <= n ; ++ i ) {
    		scanf ( "%s" , s ) ;
    		for ( int j = 0 ; j < m ; ++ j ) {
    			s[j] -= '0' ;
    			s1[j] = 1 ^ s[j] ;
    		}
    		int ans = query ( s1 ) ;
    		insert ( s ) ;
    		printf ( "%d
    " , ans ) ;
    		fflush ( stdout ) ;
    	}
    }
    
    int main () {
    	scanf ( "%d%d" , &n , &m ) ;
    	solve () ;
    	return 0 ;
    }
    

      

    J. Votter and Paul De Mort

    留坑。

    K. GCD on the segments

    考虑枚举左端点$i$,则随着右端点的右移,一共只有$O(log n)$种不同的$gcd$取值。所以首先通过ST表+二分查找预处理出$O(nlog n)$个四元组$(x,i,l,r)$,表示左端点为$i$,右端点取值范围在$[l,r]$内,且这一段的$gcd$都为$x$。

    将四元组按照$x$为第一关键字,$i$为第二关键字排序,对于相同的$x$一起处理。

    当$x$相同时,显然所有的$i$互不相同。设$f[i]$为恰好以位置$i$为结尾的最优解,则对于一个四元组$(x,i,l,r)$,能更新它的最优解为区间$[1,i-1]$的最优值$+1$,然后用它更新区间$[l,r]$的$f[]$。用支持打标记的线段树维护即可。时间复杂度$O(nlog^2n)$。

    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    const int N=100010,K=17,P=1000000007,M=262145;
    int T,n,m,i,j,x,y,l,r,mid,Log[N],val,f[K][N];
    struct PI{
      int x,i,l,r;
      PI(){}
      PI(int _x,int _i,int _l,int _r){x=_x,i=_i,l=_l,r=_r;}
    }a[3000000];
    inline bool cmp(PI a,PI b){return a.x==b.x?a.i<b.i:a.x<b.x;}
    struct Num{
      int x,y;
      Num(){x=y=0;}
      Num(int _x,int _y){x=_x,y=_y;}
      inline Num operator+(Num b){
        if(x<b.x)return b;
        if(x>b.x)return Num(x,y);
        return Num(x,(y+b.y)%P);
      }
      inline Num operator+(int _x){return Num(x+_x,y);}
      inline Num operator-(int b){return Num(x,(long long)y*b%P);}
      inline void operator+=(Num b){*this=*this+b;}
    }tmp,v[M],tag[M],ans;
    int pos[M];
    inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10LL)+=c-'0';}
    inline int askgcd(int y){int k=Log[y-i+1];return __gcd(f[k][i],f[k][y-(1<<k)+1]);}
    inline void clean(int x){
      if(pos[x]<T)pos[x]=T,v[x]=tag[x]=Num();
    }
    inline void tag1(int x,Num y){
      clean(x);
      v[x]+=y;
      tag[x]+=y;
    }
    inline void pb(int x){
      if(tag[x].x){
        tag1(x<<1,tag[x]);
        tag1(x<<1|1,tag[x]);
        tag[x]=Num();
      }
    }
    inline void up(int x){
      clean(x<<1),clean(x<<1|1);
      v[x]=v[x<<1]+v[x<<1|1];
    }
    void change(int x,int a,int b,int c,int d){
      clean(x);
      if(c<=a&&b<=d){tag1(x,tmp);return;}
      pb(x);
      int mid=(a+b)>>1;
      if(c<=mid)change(x<<1,a,mid,c,d);
      if(d>mid)change(x<<1|1,mid+1,b,c,d);
      up(x);
    }
    void ask(int x,int a,int b,int c,int d){
      clean(x);
      if(c<=a&&b<=d){tmp+=v[x];return;}
      pb(x);
      int mid=(a+b)>>1;
      if(c<=mid)ask(x<<1,a,mid,c,d);
      if(d>mid)ask(x<<1|1,mid+1,b,c,d);
      up(x);
    }
    int main(){
      for(i=2;i<=100000;i++)Log[i]=Log[i>>1]+1;
      while(~scanf("%d",&n)){
        m=0;
        ans=Num();
        for(i=1;i<=n;i++)read(f[0][i]);
        int flag=0;
        for(i=2;i<=n;i++)if(f[0][i]!=f[0][i-1]){flag=1;break;}
        if(!flag){printf("%d 1
    ",n);continue;}
        for(j=1;j<K;j++)for(i=1;i+(1<<j-1)<=n;i++)f[j][i]=__gcd(f[j-1][i],f[j-1][i+(1<<j-1)]);
        for(i=1;i<=n;i++)for(x=i;x<=n;x=y+1){
          val=askgcd(y=x),l=x+1,r=n;
          while(l<=r)if(askgcd(mid=(l+r)>>1)==val)l=(y=mid)+1;else r=mid-1;
          a[++m]=PI(val,i,x,y);
        }
        sort(a+1,a+m+1,cmp);
        for(i=1;i<=m;i++){
          if(i==1||a[i].x!=a[i-1].x)T++;
          tmp=Num();
          if(a[i].i>1)ask(1,1,n,1,a[i].i-1);
          if(!tmp.x)tmp=Num(1,1);else tmp.x++;
          ans+=tmp-(a[i].r-a[i].l+1);
          change(1,1,n,a[i].l,a[i].r);
        }
        printf("%d %d
    ",ans.x,ans.y);
      }
      return 0;
    }
    

      

    L. Fibonacci Equation

    分类讨论。

    #include<stdio.h>
    #include<algorithm>
    #include<math.h>
    #include<string.h>
    #include<string>
    #include<vector>
    #include<set>
    #include<map>
    #include<queue>
    #include<time.h>
    #include<assert.h>
    #include<iostream>
    using namespace std;
    typedef long long LL;
    typedef pair<int,int>pi;
    LL a[100];
    LL x,y,z;
    int main(){
    	/*
    	a[0]=0,a[1]=1;
    	for(int i=2;i<=30;i++)a[i]=a[i-1]+a[i-2];
    	for(int i=1;i<=25;i++){
    		printf("%lld %lld
    ",a[i],a[i]*a[i]-4*a[i-1]*a[i+1]);
    	}
    	*/
    	while(scanf("%lld%lld%lld",&x,&y,&z)!=EOF){
    		if(x==0){printf("1
    ");continue;}
    		if(y>x&&y>z){
    			if(y==3)printf("1
    ");
    			else printf("2
    ");
    		}
    		if(y<x&&y<z)printf("0
    ");
    		if(y>min(x,z)&&y<max(x,z)){
    			if(y==1)printf("2
    ");
    			else printf("0
    ");
    		}
    		//printf("real=%lld
    ",a[y]*a[y]-4*a[x]*a[z]);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    垃圾回收的可触及性
    常用的垃圾回收算法
    石子归并(区间dp 模板)
    D. Zero Quantity Maximization ( Codeforces Round #544 (Div. 3) )
    Parity game(带权并查集+离散化)
    Supermarket(贪心/并查集)
    D. Nested Segments(树状数组、离散化)
    dijkstra,belllman-ford,spfa最短路算法
    重载符
    Electrification Plan 最小生成树(prim+krusl+堆优化prim)
  • 原文地址:https://www.cnblogs.com/clrs97/p/6649222.html
Copyright © 2011-2022 走看看