题解:
设定一个初始矩阵:
\(A[10]\)表示这一年每种岁数的兔子有几只,显然初始化\(A[1]=1\)即可,然后开始推转移;
每到下一年,所有的兔子长大一岁,满十岁的兔子当场去世,然后新出生的兔子(即矩阵中的0号位)等于去年1-9岁的兔子总数之和,于是转移矩阵也搞出来了:
\(T[i-1][i]=1,T[i][0]=1\)
\(code\):
#include<cstdio>
#include<iostream>
#include<ctype.h>
#include<cstring>
#include<vector>
#define reint register int
#define mod 1000000007
#define ll long long
using namespace std;
char buf[1<<20],*p1,*p2;
inline char gc()
{
// return getchar();
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++;
}
template<typename T>
inline void read(T &x)
{
char tt;
bool flag=0;
while(!isdigit(tt=gc())&&tt!='-');
tt=='-'?(flag=1,x=0):(x=tt-'0');
while(isdigit(tt=gc())) x=(x<<1)+(x<<3)+(tt^'0');
if(flag) x=-x;
}
const int maxn=21;
inline ll add(ll a,ll b){return a+b<mod?a+b:a+b-mod;}
inline ll mul(ll a,ll b){return a*b<mod?a*b:a*b%mod;}
struct arr{
int n,m;
ll a[21][21];
inline arr(int c=0,int d=0)
{
memset(a,0,sizeof(a));
n=c,m=d;
}
arr operator*(arr b) const
{
arr c;
c.n=n;c.m=b.m;
// for(reint i=0;i<n;i++,putchar(10))
// for(reint j=0;j<m;j++)
// printf("%d ",a[i][j]);
// putchar(10);
for(reint i=0;i<n;i++)
for(reint j=0;j<c.m;j++)
for(reint k=0;k<m;k++)
c.a[i][j]=add(c.a[i][j],mul(a[i][k],b.a[k][j]));
return c;
}
};
arr mg(arr a,ll b)
{
arr ans;
ans=arr(11,11);
for(reint i=0;i<11;i++)
ans.a[i][i]=1;
while(b)
{
if(b&1) ans=ans*a;
a=a*a;
b>>=1;
}
return ans;
}
ll n,out_;
arr a,b,ans;
int main()
{
read(n);
a=arr(1,11);
a.a[0][1]=1;
b=arr(11,11);
for(reint i=1;i<=9;i++)
b.a[i][0]=1,b.a[i-1][i]=1;
b.a[10][0]=1;
ans=a*mg(b,n-1);
for(reint i=0;i<11;i++)
out_=add(out_,ans.a[0][i]);
printf("%lld",out_);
}
题解:
莫队维护区间逆序对个数,考虑每次增加或减去当前\(Pos\)对逆序对总数做出的贡献;
\(code:\)
#include<cstdio>
#include<iostream>
#include<ctype.h>
#include<cstring>
#include<vector>
#include<cmath>
#include<algorithm>
#define reint register int
#define mod 1000000007
#define ll long long
using namespace std;
char buf[1<<20],*p1,*p2;
inline char gc()
{
// return getchar();
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++;
}
template<typename T>
inline void read(T &x)
{
char tt;
bool flag=0;
while(!isdigit(tt=gc())&&tt!='-');
tt=='-'?(flag=1,x=0):(x=tt-'0');
while(isdigit(tt=gc())) x=(x<<1)+(x<<3)+(tt^'0');
if(flag) x=-x;
}
const int maxn=30002;
struct node{
int x,y,id;
inline node(int a=0,int b=0,int c=0)
{x=a,y=b,id=c;}
}q[maxn];
int c[maxn],n,a[maxn],s,m,Ans;
int l=1,r,ans[maxn],block[maxn];
bool cmp(node a,node b)
{
return block[a.x]==block[b.x]?a.y<b.y:block[a.x]<block[b.x];
}
int lowbit(int x)
{
return x&-x;
}
void modify(int x,int d)
{
for(reint i=x;i<=n;i+=lowbit(i)) c[i]+=d;
}
int query(int x)
{
int sum=0;
for(reint i=x;i;i^=lowbit(i)) sum+=c[i];
return sum;
}
void del(int pos,int id)
{
if(id==0)
{
int getmin=query(a[pos]-1);
Ans-=getmin;
}
else
{
int getmax=query(n)-query(a[pos]);
Ans-=getmax;
}
modify(a[pos],-1);
}
void add(int pos,int id)
{
if(id==0)
{
int getmin=query(a[pos]-1);
Ans+=getmin;
}
else
{
int getmax=query(n)-query(a[pos]);
Ans+=getmax;
}
modify(a[pos],1);
}
int main()
{
read(n);
s=pow(n,0.6666);
for(reint i=1;i<=n;i++) read(a[i]);
read(m);
for(reint i=1;i<=m;i++)
{
int x,y;
read(x),read(y);
q[i]=node(x,y,i);
}
for(reint i=1;i<=n;i++)
block[i]=(i-1)/s+1;
sort(q+1,q+1+m,cmp);
for(reint i=1;i<=m;i++)
{
while(r<q[i].y) add(++r,1);
while(r>q[i].y) del(r--,1);
while(l<q[i].x) del(l++,0);
while(l>q[i].x) add(--l,0);
ans[q[i].id]=Ans;
}
for(int i=1;i<=m;i++)
printf("%d\n",ans[i]);
}
题解:
本题较水,显然暴力所有点连边会瞬间飞起,于是考虑优化建图;
对横坐标排序,相邻连边;对纵坐标排序,相邻连边;一遍迪杰斯特拉,完;
\(code:\)
#include<cstdio>
#include<iostream>
#include<ctype.h>
#include<cstring>
#include<vector>
#include<algorithm>
#include<queue>
#define reint register int
#define ll long long
using namespace std;
char buf[1<<20],*p1,*p2;
inline char gc()
{
// return getchar();
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++;
}
template<typename T>
inline void read(T &x)
{
char tt;
bool flag=0;
while(!isdigit(tt=gc())&&tt!='-');
tt=='-'?(flag=1,x=0):(x=tt-'0');
while(isdigit(tt=gc())) x=(x<<1)+(x<<3)+(tt^'0');
if(flag) x=-x;
}
const int maxn=200002;
struct point{
int x,y,id;
inline point(int a=0,int b=0,int c=0)
{x=a,y=b;id=c;}
}a[maxn];
struct node{
int x,len;
inline node(int a=0,int b=0)
{x=a,len=b;}
inline bool operator<(node a)const
{return len>a.len;}
};
bool cmpx(point a,point b)
{return a.x<b.x;}
bool cmpy(point a,point b)
{return a.y<b.y;}
int n,dis[maxn];
vector<node>G[maxn];
priority_queue<node>q;
int cal(point a,point b)
{
return min(abs(a.x-b.x),abs(a.y-b.y));
}
void djs()
{
for(reint i=1;i<=n;i++) dis[i]=1e9;
dis[1]=0;
q.push(node(1,0));
while(!q.empty())
{
int x=q.top().x;
int len=q.top().len;
q.pop();
if(dis[x]!=len) continue;
for(reint i=G[x].size()-1;i>=0;i--)
{
int p=G[x][i].x;
len=G[x][i].len;
if(dis[p]<=dis[x]+len) continue;
dis[p]=dis[x]+len;
q.push(node(p,dis[p]));
}
}
}
int main()
{
read(n);
for(reint i=1;i<=n;i++)
{
int x,y;
read(x),read(y);
a[i]=point(x,y,i);
}
sort(a+1,a+1+n,cmpx);
for(reint i=1;i<n;i++)
{
G[a[i].id].push_back(node(a[i+1].id,cal(a[i],a[i+1])));
G[a[i+1].id].push_back(node(a[i].id,cal(a[i],a[i+1])));
}
sort(a+1,a+1+n,cmpy);
for(reint i=1;i<n;i++)
{
G[a[i].id].push_back(node(a[i+1].id,cal(a[i],a[i+1])));
G[a[i+1].id].push_back(node(a[i].id,cal(a[i],a[i+1])));
}
djs();
printf("%d",dis[n]);
}