适应acm赛制看来不是我原先想的那么简单...
4360
双关键字单源最短路
这道题我交了10+次,原因是初始化没取最小值...看来确实是太久没在考试状态下写题了,心中竟然还在紧张
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
const long long oo=1314520LL*13520LL+1;
using namespace std;
int n,m,ss,t;
int next[2000000],sora[2000000],pow[2000000],tail[2000000];
long long cost[2000000],d[2000][4];
int dd[2000][4],st[2000000][2];
bool v[2000][4];
char ch[2000];
void origin()
{
ss=n;
for (int i=0;i<=n;i++) tail[i]=i,next[i]=0;
ch['L']=0,ch['O']=1,ch['V']=2,ch['E']=3;
}
void link(int x,int y,int z,int c)
{
++ss,next[tail[x]]=ss,tail[x]=ss,sora[ss]=y,cost[ss]=z,pow[ss]=c,next[ss]=0;
++ss,next[tail[y]]=ss,tail[y]=ss,sora[ss]=x,cost[ss]=z,pow[ss]=c,next[ss]=0;
}
void spfa(int s)
{
int h,r=h=0,ne,na,tmp,ns;
memset(v,0,sizeof(v));
memset(d,127,sizeof(d)),memset(dd,129,sizeof(dd));
for (int i=s;next[i];) {
i=next[i],ne=sora[i];
if (pow[i]==0) {
d[ne][0]=min(d[ne][0],cost[i]);
dd[ne][0]=1;
st[++r][0]=ne,st[r][1]=0;
v[ne][0]=1;
}
}
for (;h<r;) {
ne=st[++h][0],ns=st[h][1];
for (int i=ne;next[i];) {
i=next[i],na=sora[i],tmp=pow[i];
if ((ns+1)%4==pow[i])
if (d[ne][ns]+cost[i]<d[na][tmp] || ((d[ne][ns]+cost[i]==d[na][tmp]) && (dd[ne][ns]+1>dd[na][tmp]))) {
d[na][tmp]=d[ne][ns]+cost[i],dd[na][tmp]=dd[ne][ns]+1;
if (!v[na][tmp]) {
v[na][tmp]=1;
st[++r][0]=na,st[r][1]=tmp;
}
}
}
v[ne][ns]=0;
}
}
void init(int cas)
{
int x,y,z;
//char ch1,ch2;
scanf("%d%d\n",&n,&m);
origin();
char ch2[100]={};
for (int i=1;i<=m;i++) {
scanf("%d%d%d%s\n",&x,&y,&z,ch2);
link(x,y,z,ch[ch2[0]]);
}
/*if (1==n) {
printf("Case %d: Cute Sangsang, Binbin will come with a donkey after travelling %I64d meters and finding %d LOVE strings at last.\n",cas,0,0);
return ;
}*/
spfa(1);
if (d[n][3]>=d[0][0]) printf("Case %d: Binbin you disappoint Sangsang again, damn it!\n",cas);
else printf("Case %d: Cute Sangsang, Binbin will come with a donkey after travelling %I64d meters and finding %d LOVE strings at last.\n",cas,d[n][3],dd[n][3]/4);
}
int main()
{
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
cin>>t;
for (int i=1;i<=t;i++) init(i);
return 0;
}
4362
dp+单调指针
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
int ans,f[100][2000],n,m,a[100][2000],b[100][2000],x,t,u[100][2000],e,mi;
bool cmp(int i,int j)
{
return a[e][i]<a[e][j];
}
void init()
{
scanf("%d%d%d\n",&m,&n,&x);
for (int i=1;i<=m;i++)
for (int j=1;j<=n;j++) scanf("%d",&a[i][j]),u[i][j]=j;
for (int i=1;i<=m;i++)
for (int j=1;j<=n;j++) scanf("%d",&b[i][j]);
memset(f,127,sizeof(f));
e=1;
sort(u[1]+1,u[1]+n+1,cmp);
for (int i=1;i<=n;i++) f[1][i]=abs(x-a[1][u[1][i]])+b[1][u[1][i]];
for (int i=2;i<=m;i++) {
e=i;
sort(u[i]+1,u[i]+n+1,cmp);
mi=f[0][0];
for (int j=1,k=1;j<=n;j++) {
for (;(k<=n) && (a[i-1][u[i-1][k]]<=a[i][u[i][j]]);k++)
mi=min(mi,f[i-1][k]-a[i-1][u[i-1][k]]);
if (mi!=f[0][0]) f[i][j]=min(f[i][j],mi+b[i][u[i][j]]+a[i][u[i][j]]);
}
mi=f[0][0];
for (int j=n,k=n;j>=1;j--) {
for (;(k>=1) && (a[i-1][u[i-1][k]]>=a[i][u[i][j]]);k--)
mi=min(mi,f[i-1][k]+a[i-1][u[i-1][k]]);
if (mi!=f[0][0]) f[i][j]=min(f[i][j],mi+b[i][u[i][j]]-a[i][u[i][j]]);
}
}
ans=f[0][0];
for (int i=1;i<=n;i++) ans=min(ans,f[m][i]);
printf("%d\n",ans);
}
int main()
{
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
cin>>t;
for (;t;t--) init();
return 0;
}
4363
dp->打表
dp各种特判,不过考虑和写的时候还蛮谨慎的,一遍过
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
const long long mo=1000000007LL;
using namespace std;
int n,m,time,o[5];
long long f[41][41][5][5][5][5][2];
int doit(int i,int j,int k,int p)
{
int v[5]={};
v[i]=v[j]=v[k]=v[p]=1;
int sum=0;
for (int i=1;i<=4;i++)
sum+=(v[i]==0);
return sum;
}
int main()
{
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
n=m=40;
time=0;
memset(f,0,sizeof(f));
for (int i=0;i<=4;i++)
for (int j=0;j<=4;j++)
for (int k=0;k<=4;k++)
for (int p=0;p<=4;p++) {
++time;
o[i]=o[j]=o[k]=o[p]=time;
for (int y=1;y<=4;y++)
if (o[y]!=time) {
f[1][1][i][j][k][p][0]++;
f[1][1][i][j][k][p][1]++;
}
}
for (int c=1;c<=n;c++)
for (int h=1;h<=m;h++) {
if (c==1 && h==1) continue;
for (int e=0;e<=1;e++)
for (int i=0;i<=4;i++)
for (int j=0;j<=4;j++)
for (int k=0;k<=4;k++)
for (int p=0;p<=4;p++) {
++time;
o[i]=o[j]=o[k]=o[p]=time;
for (int y=1;y<=4;y++)
if (o[y]!=time) {
f[c][h][i][j][k][p][e]++;
}
if (!e) {
++time;
o[i]=o[j]=o[k]=time;
for (int y=1;y<=4;y++)
if (o[y]!=time) {
f[c][h][i][j][k][p][e]+=(c-1)*doit(i,y,k,p);
}
for (int v=1;v<c;v++) {
for (int y=1;y<=4;y++)
if (o[y]!=time) {
(f[c][h][i][j][k][p][e]+=f[c-v][h][i][y][k][p][e^1]-doit(i,y,k,p)+mo)%=mo;
}
}
++time;
o[i]=o[p]=o[k]=time;
for (int v=1;v<c;v++) {
for (int y=1;y<=4;y++)
if (o[y]!=time) {
(f[c][h][i][j][k][p][e]+=f[v][h][i][j][k][y][e^1]-doit(i,j,k,y)+mo)%=mo;
}
}
}
if (e) {
++time;
o[i]=o[j]=o[p]=time;
for (int y=1;y<=4;y++)
if (o[y]!=time) {
f[c][h][i][j][k][p][e]+=(h-1)*doit(y,j,k,p);
}
for (int v=1;v<h;v++) {
for (int y=1;y<=4;y++)
if (o[y]!=time) {
(f[c][h][i][j][k][p][e]+=f[c][h-v][y][j][k][p][e^1]-doit(y,j,k,p)+mo)%=mo;
}
}
++time;
o[j]=o[k]=o[p]=time;
for (int v=1;v<h;v++) {
for (int y=1;y<=4;y++)
if (o[y]!=time) {
(f[c][h][i][j][k][p][e]+=f[c][v][i][j][y][p][e^1]-doit(i,j,y,p)+mo)%=mo;
}
}
}
}
}
for (int i=1;i<=n;i++) {
printf("{0,");
for (int j=1;j<=m;j++) {
printf("%lldLL",(f[i][j][0][0][0][0][0]+mo)%mo);
if (j!=m) printf(",");
}
printf("},\n");
}
return 0;
}
4364
模拟
比赛时题都没读...不过理解题意确实有点麻烦,最坑的是,输出时只保留两个字节,一开始不知道wa在哪,最后阴差阳错改了输出给过了...
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
const int lim=15*16+15;
using namespace std;
struct mt{int m[5][5];}o,a,c;
int t;
char ch[20000];
int doit(int x,int y)
{
if (1==x) return y;
else if (2==x) {
y<<=1;
if (y>lim) return y^(16+11);
return y;
}
else {
int z=y;
y<<=1;
if (y>lim) y=y^(16+11);
return y^z;
}
}
void mul(mt &ans,mt a,mt b)
{
memset(ans.m,0,sizeof(ans.m));
for (int i=1;i<=4;i++)
for (int j=1;j<=4;j++)
for (int k=1;k<=4;k++) {
ans.m[i][j]^=doit(a.m[i][k],b.m[k][j]);
}
}
void init()
{
memset(a.m,0,sizeof(a.m));
for (int i=1;i<=4;i++) {
for (int j=1;j<=4;j++) {
scanf("%s",ch+1);
if (ch[1]>='A' && ch[1]<='Z') a.m[i][j]=(ch[1]-'A'+10)*16;
else a.m[i][j]=(ch[1]-'0')*16;
if (ch[2]>='A' && ch[2]<='Z') a.m[i][j]+=ch[2]-'A'+10;
else a.m[i][j]+=ch[2]-'0';
}
scanf("\n");
}
mul(c,o,a);
for (int i=1;i<=4;i++) {
for (int j=1;j<=4;j++) {
int ans[5]={},s=0;
for (;c.m[i][j];c.m[i][j]/=16) ans[++s]=c.m[i][j]%16;
for (s=2;s;s--)
if (ans[s]>=10) printf("%c",ans[s]-10+'A');
else printf("%d",ans[s]);
if (j!=4) printf(" ");
// printf(" ");
}
printf("\n");
}
if (t>1) printf("\n");
//printf("\n");
}
int main()
{
freopen("input.txt","r",stdin);
freopen("ansput.txt","w",stdout);
o.m[1][1]=2,o.m[1][2]=3,o.m[1][3]=1,o.m[1][4]=1;
o.m[2][1]=1,o.m[2][2]=2,o.m[2][3]=3,o.m[2][4]=1;
o.m[3][1]=1,o.m[3][2]=1,o.m[3][3]=2,o.m[3][4]=3;
o.m[4][1]=3,o.m[4][2]=1,o.m[4][3]=1,o.m[4][4]=2;
scanf("%d\n",&t);
for (;t;t--) init();
return 0;
}
4365
归一到一个三角形的等价类中,快速幂
比赛时没时间调了,结果只归一到左上角矩阵中
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
const long long mo=100000007LL;
using namespace std;
long long n,m,tot,ans,k;
int x[2000000],y[2000000],u[2000000];
long long fgm(long long b,long long e,long long mo)
{
long long ans=1;
for (;e;b=(b*b)%mo,e>>=1)
if (e&1) ans=(ans*b)%mo;
return ans;
}
bool cmp(int i,int j)
{
if (x[i]!=x[j]) return x[i]<x[j];
return y[i]<y[j];
}
void init()
{
tot=m;
for (int i=1;i<=m;i++) {
scanf("%d%d\n",&x[i],&y[i]);x[i]++,y[i]++;
++tot;
x[tot]=y[i],y[tot]=n-x[i]+1;
++tot;
x[tot]=n-x[i]+1,y[tot]=n-y[i]+1;
++tot;
x[tot]=n-y[i]+1,y[tot]=x[i];
}
m=tot;
for (int i=1;i<=m;i++) {
++tot;
x[tot]=x[i],y[tot]=n-y[i]+1;
++tot;
x[tot]=n-x[i]+1,y[tot]=y[i];
}
for (int i=1;i<=tot;i++) u[i]=i;
sort(u+1,u+tot+1,cmp);
x[0]=y[0]=u[0]=0;
if (n&1) {
ans=((n/2+1)*(n/2+1)-(n/2+1))/2+(n/2+1);
}
else {
ans=((n/2)*(n/2)-n/2)/2+n/2;
}
for (int i=1;i<=tot;i++)
if (x[u[i]]!=x[u[i-1]] || y[u[i]]!=y[u[i-1]]) {
if (n&1) {
if (x[u[i]]<=n/2+1 && y[u[i]]>=x[u[i]] && y[u[i]]<=n/2+1) ans--;
}
else {
if (x[u[i]]<=n/2 && y[u[i]]>=x[u[i]] && y[u[i]]<=n/2) ans--;
}
}
cout<<fgm(k,ans,mo)<<endl;
}
int main()
{
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
for (;cin>>n>>m>>k;) init();
return 0;
}
4366
先维护数值大小,再维护dfs序
首先是看错题,再者是没想到交换两个序的顺序,真是太颓废了
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
int ans[200000],ab[200000],lo[200000],tail[200000],next[2000000],sora[2000000];
int ss,m1,n,m,b[2000000],l[2000000],r[2000000],h,u[200000],t;
void origin()
{
ss=n;
for (int i=1;i<=n;i++) tail[i]=i,next[i]=0;
for (m1=1;m1<=n+2;m1<<=1) ;
for (int i=1;i<=m1+m1;i++) b[i]=0;
}
void link(int x,int y)
{
ss++,next[tail[x]]=ss,tail[x]=ss,sora[ss]=y,next[ss]=0;
}
void dfs(int x)
{
l[x]=++h;
for (int i=x,ne;next[i];) {
i=next[i],ne=sora[i];
dfs(ne);
}
r[x]=h;
}
bool cmp(int i,int j)
{
return ab[i]>ab[j];
}
int max(int x,int y)
{
return (lo[x]>lo[y]) ? x : y;
}
void change(int x,int y)
{
x+=m1,b[x]=y;
for (x>>=1;x;x>>=1) b[x]=max(b[x<<1],b[(x<<1)+1]);
}
int ask(int l,int r)
{
l+=m1-1,r+=m1+1;
int ans=0;
for (;!((l^r)==1);l>>=1,r>>=1) {
if ((l&1)==0) ans=max(ans,b[l^1]);
if ((r&1)==1) ans=max(ans,b[r^1]);
}
return ans;
}
void init()
{
int x;
scanf("%d%d\n",&n,&m);
origin();
for (int i=2;i<=n;i++) {
scanf("%d%d%d\n",&x,&lo[i],&ab[i]);x++;
link(x,i);
}
h=0;
dfs(1);
for (int i=2;i<=n;i++) u[i]=i;
sort(u+2,u+n+1,cmp);
lo[0]=-1;
for (int i=2,j=2;i<=n;i++) {
for (;(j<=i) && (ab[u[j]]>ab[u[i]]);j++) change(l[u[j]],u[j]);
ans[u[i]]=ask(l[u[i]],r[u[i]]);
}
for (int i=1;i<=m;i++) {
scanf("%d\n",&x);x++;
printf("%d\n",ans[x]-1);
}
}
int main()
{
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
cin>>t;
for (;t;t--) init();
return 0;
}