contest 1.20

B.矩阵快速幂

等比数列二分求和

#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
 
int n,k,mod;
const int MAXN=35;
struct Mat{
    int n,m;
    int mat[MAXN][MAXN];
    Mat(){
        memset(mat,0,sizeof(mat));
        n=MAXN,m=MAXN;
    }
    Mat(int x,int y){
        memset(mat,0,sizeof(mat));
        n=x,m=y;
    };
    Mat operator*(Mat b){
        Mat c(n,b.m);
        for(int i=0;i<n;i++)
            for(int j=0;j<b.m;j++){
                for(int k=0;k<m;k++){
                    c.mat[i][j]+=(mat[i][k]*b.mat[k][j])%mod;
                    c.mat[i][j]%=mod;
                }
            }
        return c;
    }
    Mat operator+(Mat b){
        Mat c(n,m);
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
                c.mat[i][j]=(mat[i][j]+b.mat[i][j])%mod;
        return c;
    }
    void in(){
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
                scanf("%d",&mat[i][j]);
    }
    void out(){
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++)
                printf("%d%c",mat[i][j],j==m-1?'\n':' ');
        }
    }
}E;
 
Mat qpow(Mat a,int b){Mat ret=E; while(b){ if(b&1) ret=ret*a; a=a*a; b>>=1;} return ret;}
 
Mat cal(Mat a,int k){//二分求等比数列和--a+a^2+a^3+...+a^k
  if(k==1) return a;
  else if(k&1){
    Mat cur=qpow(a,k/2+1);
    return cal(a,k/2)*(E+cur)+cur;
  }
  else return cal(a,k/2)*(E+qpow(a,k/2));
}
 
int main()
{
    scanf("%d%d%d",&n,&k,&mod);
    E.n=n,E.m=n;
    for(int i=0;i<n;i++)
      for(int j=0;j<n;j++)
        E.mat[i][j]=(i==j?1:0);
    Mat now(n,n);
    now.in();
    now=cal(now,k);
    now.out();
    return 0;
}
View Code

C.发财兔序列

莫队+离散化+set

#include <iostream>
#include<cstdio>
#include<cmath>
#include<set>
#include<algorithm>
using namespace std;

set<int> s;set<int>::iterator it;
int n,m;
int a[100005],b[100005],z;
struct Query{int l,r,id;}q[100005];
int cnt[100005],tot[100005];
int ans[100005];
int maxn=1;

int getid(int x){return lower_bound(b+1,b+1+z,x)-b;}

bool cmp(Query a,Query b){
  int block=sqrt(n);
  if(a.l/block!=b.l/block) return a.l/block<b.l/block;
  else return a.r<b.r;
}

inline void add(int pos){
  int id=getid(a[pos]);
  tot[cnt[id]]--;
  if(tot[cnt[id]]==0) s.erase(cnt[id]);
  cnt[id]++;
  tot[cnt[id]]++;
  if(tot[cnt[id]]==1) s.insert(cnt[id]);
  it=s.end(); it--;
  maxn=*it;
}

inline void sub(int pos){
  int id=getid(a[pos]);
  tot[cnt[id]]--;
  if(tot[cnt[id]]==0) s.erase(cnt[id]);
  cnt[id]--;
  tot[cnt[id]]++;
  if(tot[cnt[id]]==1) s.insert(cnt[id]);
  it=s.end(); it--;
  maxn=*it;
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i];
    sort(b+1,b+1+n);z=unique(b+1,b+1+n)-(b+1);
    for(int i=1;i<=m;i++){
        scanf("%d%d",&q[i].l,&q[i].r);
        q[i].id=i;
    }
    sort(q+1,q+1+m,cmp);
    int L=1,R=0;
    for(int i=1;i<=m;i++){
        while(q[i].r>R) R++,add(R);
        while(q[i].r<R) sub(R),R--;
        while(q[i].l>L) sub(L),L++;
        while(q[i].l<L) L--,add(L);
        ans[q[i].id]=maxn;
    }
    for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
    return 0;
}
View Code

E.发财兔求和

先把各个颜色分离,再把同种颜色中的奇编号和偶编号分离

推公式

#include <iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#define mod 10007
typedef long long ll;
using namespace std;

ll n,m;
struct Node{ll id,num;};
ll color[100005],num[100005];
vector<Node> v1[100005];
vector<Node> v2[100005];

int main()
{
    scanf("%lld%lld",&n,&m);
    for(ll i=1;i<=n;i++) scanf("%lld",&num[i]);
    for(ll i=1;i<=n;i++) scanf("%lld",&color[i]);
    for(ll i=1;i<=n;i++){
        if(i%2==1) v1[color[i]].push_back(Node{i,num[i]});
        else v2[color[i]].push_back(Node{i,num[i]});
    }
    ll ans=0;
    for(ll i=1;i<=m;i++){
        if(v1[i].size()!=0){
          ll siz=v1[i].size();
          ll sum_num=0,sum_id=0,sum_product=0;
          for(ll j=0;j<siz;j++){
            sum_id=(sum_id+v1[i][j].id)%mod;
            sum_num=(sum_num+v1[i][j].num)%mod;
            sum_product=(sum_product+v1[i][j].id*v1[i][j].num%mod)%mod;
          }
          for(ll j=0;j<siz;j++){
            ans=(ans+(siz-1)*v1[i][j].id%mod*v1[i][j].num%mod+v1[i][j].id*(sum_num-v1[i][j].num)%mod+v1[i][j].num*(sum_id-v1[i][j].id)%mod+(sum_product-v1[i][j].id*v1[i][j].num%mod))%mod;
          }
        }
        if(v2[i].size()!=0){
          ll siz=v2[i].size();
          ll sum_num=0,sum_id=0,sum_product=0;
          for(ll j=0;j<siz;j++){
            sum_id=(sum_id+v2[i][j].id)%mod;
            sum_num=(sum_num+v2[i][j].num)%mod;
            sum_product=(sum_product+v2[i][j].id*v2[i][j].num%mod)%mod;
          }
          for(ll j=0;j<siz;j++){
            ans=(ans+(siz-1)*v2[i][j].id%mod*v2[i][j].num%mod+v2[i][j].id*(sum_num-v2[i][j].num)%mod+v2[i][j].num*(sum_id-v2[i][j].id)%mod+(sum_product-v2[i][j].id*v2[i][j].num%mod))%mod;
          }
        }
    }
    ans=(ans+mod)%mod;
    ans=ans*5004%mod;
    printf("%lld\n",ans);
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/lllxq/p/10294840.html