看到别人电脑疯狂死机,把还原系统关掉从而电脑从不死机的我很有优越感
最近考的都是什么东西啊,四题三题是超出noip的算法。炸得一塌糊涂(stO cqr and cjx Orz)
T1 签。暴力算法是直接跑O(nmk)对每个输入老老实实地在矩阵里进行一遍,然后边算边取模,非常好实现也不容易出错。但是注意到题目中k非常小,只有1000,所以可以预处理每行和每列的总和,然后在这k次操作中直接调用,行与列之间重复的计算再单独加上(或减去)一遍。这样基本就能在时限内拿下。但是代码实现比较容易出错,细节也比较多,祥见代码。我赛时把暴力和正解都打了,然后正解炸了只有50分。赛后发现:不开longlong见祖宗。总之我把代码贴这里了(约200行,相当炸裂)
#include
using namespace std;
int x,y,n,m,k;
//vectorh[1000005],l[1000005];
long long int h[1000005],l[1000005];
long long int sh[1000005],sl[1000005],ans,sb[1005][1005];
vectorfh;
vectorfl;
char a;
int sol(int hh,int ll)
{
return ((hh-1)*m+ll)%1000000007;
}
int main()
{
freopen("wisdom.in","r",stdin);
freopen("wisdom.out","w",stdout);
cin>>n>>m>>k;
if(n<=1000&&m<=1000)
{
// cout<<"A"<<endl;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
sb[i][j]=sol(i,j);
}
}
// for(int i=1;i<=n;i++)
// {
// for(int j=1;j<=m;j++)
// {
// cout<<sb[i][j]<<" ";
// }
// cout<<endl;
// }
for(int i=1;i>a>>x>>y;
if(a=='R')
{
for(int j=1;j<=m;j++)
{
sb[x][j]*=y;
sb[x][j]%=1000000007;
}
}
else
{
for(int j=1;j<=n;j++)
{
sb[j][x]*=y;
sb[j][x]%=1000000007;
}
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
// cout<<sb[i][j]<<" ";
ans+=sb[i][j];
ans%=1000000007;
}
// cout<<endl;
}
cout<<ans<<endl;
}
else
{
for(int i=1;i<=1000000;i++)
{
h[i]=-1;
l[i]=-1;
}
for(int i=1;i>a>>x>>y;
if(a=='R')
{
// h[x].push_back(y);
if(h[x]==-1)
{
h[x]=y;
fh.push_back(x);
// cout<<"+++++++++++++ "<<x<<endl;
}
else
{
h[x]*=y;
h[x]%=1000000007;
}
}
else
{
// l[x].push_back(y);
if(l[x]==-1)
{
l[x]=y;
fl.push_back(x);
}
else
{
l[x]*=y;
l[x]%=1000000007;
}
}
}
for(int i=1;i<=n;i++)
{
sh[i]=(((i-1)*m+1+i*m)*m/2)%1000000007;
}
for(int i=1;i<=n;i++)
{
sl[1]+=(i-1)*m+1;
}
sl[1]%=1000000007;
for(int i=2;i<=m;i++)
{
sl[i]=sl[1]+n*(i-1);
sl[i]%=1000000007;
}
for(int i=1;i<=n;i++)
{
ans+=sh[i];
ans%=1000000007;
}
// cout<<"-- "<<ans<<endl;
// for(int i=1;i<=n;i++)
// {
// cout<<sh[i]<<" ";
// }
// cout<<endl;
// for(int i=1;i<=m;i++)
// {
// cout<<sl[i]<<" ";
// }
// cout<<endl;
for(int i:fh)
{
// cout<<"--+ "<<i<<endl;
ans+=sh[i]*(h[i]-1);
ans%=1000000007;
// cout<<"==== "<<ans<<" "<<i<<" "<<h[i]<<endl;
}
// cout<<" 1 ----- "<<ans<<endl;
for(int i:fl)
{
ans+=sl[i]*(l[i]-1);
// pl[i]++;
ans%=1000000007;
}
// for(int i=0;i<=1000000;i++)
// {
// pl[i]=0;
// ph[i]=0;
// }
// cout<<"__DWDWD"<<endl;
// cout<<h[2][0]<<endl;
for(int i:fh)
{
for(int j:fl)
{
// cout<<i<<" "<<j<<" "<<ph[i]<<" "<<pl[j]<<" "<<h[i][ph[i]]<<" "<<l[j][pl[j]]<<endl;
// if(vla[j]==0&&vha[i]==0)
{
ans+=(((h[i]-1)*(l[j]-1)%1000000007)*sol(i,j))%1000000007;
ans%=1000000007;
// pl[j]++;
// ph[i]++;
}
}
// for(int i=1;i<=1000;i++)
// {
// pl[i]=0;
// }
}
cout<<ans<<endl;
}
}
T2 赛时想出dp做法。根据每次电梯到达的楼层作为子问题处理,推出dp[i]=min(dp[i],dp[j]+(n-sum[j])(i-1)2).但是在处理k时出了问题,最后因为多测炸了(我可是过了两个大样例啊!!)正解是李超线段树(那边的教练想出的优先队列做法还假了),不懂,不讲,详见cjx或cqr的blog
T3 赛时脑抽没打暴力,赛后直接dfs能拿到可观的分数。观察数据发现n非常小以至于可以用dfs。然后暴力处理m。正解是FWT,不懂,不讲
T4 T4死了