B.矩阵快速幂
等比数列二分求和
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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?' ':' '); } } }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; }
C.发财兔序列
莫队+离散化+set
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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 ",ans[i]); return 0; }
E.发财兔求和
先把各个颜色分离,再把同种颜色中的奇编号和偶编号分离
推公式
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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 ",ans); return 0; }
D.有趣的数
构造
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include<cstdio> #include<cstring> #include<algorithm> typedef long long ll; using namespace std; ll p[20]; ll k,m,len; char s[20]; ll cal(ll x){ sprintf(s,"%lld",x); len=strlen(s); ll now=1,t=0,ret=0; for(ll i=0;i<len;i++){ t=t*10+s[i]-'0'; ret+=(t-now+1); now*=10; } return ret; } int main() { p[0]=1; for(ll i=1;i<=18;i++) p[i]=p[i-1]*10; scanf("%lld%lld",&k,&m); ll flag=-1; for(ll i=0;i<=18;i++){ if(p[i]==k) {flag=i;break;} } if(flag!=-1){ if(flag+1==m) printf("%lld ",k); else puts("0"); return 0; } ll min_m=cal(k); if(m==min_m) printf("%lld ",k); else if(m<min_m) puts("0"); else{ m-=min_m; ll ans=p[len],now=1; while(1){ ll tmp=k*p[now]-ans; if(tmp>=m) break; else{ m-=tmp; now++,ans*=10; } } ans+=m-1; printf("%lld ",ans); } return 0; }