T1:倍增
可以把这个图看作一棵树
...
#define fr(i,a,b) for(int i=(a),_end_=(b);i<=_end_;i++)
#define fd(i,a,b) for(int i=(a),_end_=(b);i>=_end_;i--)
int p[60],f[60],n,t,m,mp[60][60];
int getf(int x){
p[x]=1;
f[x]=0;
fr(i,1,n)
if(mp[x][i]&&!p[i])
f[x]=max(f[x],getf(i));
f[x]++;
return f[x];
}
int cmp(int x,int y){
return f[x]>f[y];
}
long long getans(int x,int w){
int len=0,k[60];
memset(k,0,sizeof(k));
p[x]=1;
fr(i,1,n)
if(mp[x][i]&&!p[i])
k[++len]=i;
if(!len)
return w;
sort(k+1,k+len+1,cmp);
long long dans=getans(k[1],w*2+1);
fr(i,2,len)dans+=getans(k[i],1);
return dans;
}
int main(){
...
while(t--){
...
if(n==1){
puts("0");
continue;
}
memset(p,0,sizeof(p));
getf(m);
int flag=0;
fr(i,1,n)
if(f[i]==0){
puts("-1");
flag=1;
break;
}
if(flag)continue;
flag=0;
fr(i,1,n){
fr(j,1,n)if(mp[i][j])goto tooooo;
printf("-1\n");
flag=1;
tooooo:;
}
if(flag)continue;
memset(p,0,sizeof(p));
long long ans=getans(m,0);
printf("%lld\n",ans>2000000000?-1:ans);
}
return 0;
}
T2:
直接不断平方取余
...
int main(){
...
while(n--)ans=(ans*ans)%10007;
printf("%d\n",ans);
return 0;
}
T3:递推
f[i,j,k]=min(f[i−1,j,k],f[i,j−1,k],f[i,j,k−1])+a[i,j,k]
T4:DP
假设有两个人在走,里起点的距离一定是相等的
f[i,j,k,l,o,p]分别表示两个人的坐标
f[i,j,k,l,o,p]=min(f[i−x1,j−x2,k−x3,l−x4,o−x5,p−x6])(x1+x2+x3=x4+x5+x6=1;x1,x2,x3,x4,x5,x6∈0,1)+a[i,j,k]
f[i,j,k,l,o,p]+=a[l,o,p](ijk≠lop;l+j+k≠l+o+p)