半集训训练 8.28 「路,还是要自己走的」

这次吧,就是最大能力了,发挥的很正常。

自己也不再那么天真了,更追求实际的东西了。

T1 chinese

  一道好题,考察的是对于公式实际意义的理解和转化题目的能力。

  考场上一眼看上去啥都不会,但是看了眼数据,5以内60分,嘿嘿嘿……

  打着表,就跳了这道题。

  下面讲正解。

  我们可以知道$f_i$的定义(炼字为i个的方案数),然后考虑$f_i*i$的实际含义。

  不难发现,其含义就是炼字为i个的时候总的炼字个数

  那么$\sum \limits _{i=0}^{n*m} f_i*i$就是总的炼字的个数。

  很神奇对不对!当我自说自话。

  那么这样转化之后,我们发现每个点的贡献互不影响

  所以我们只需要计算每个点的贡献就可以了。

  而这个贡献又由什么来确定呢?

  假设$(x,y)$为炼字,那么我们就要保证$(i,y)$,$(x,j)$上的点权都要小于$(x,y)$,这些点之间的方案又互不影响,所以可以得出${(k-1)}^{n-1}*{(k-1)}^{m-1}$这个式子。

  我们看出其中有些问题,也就是我们的炼字的权值不一定是$k$,这就是我们需要枚举的地方,也就是${(i-1)}^{n-1}*{(i-1)}^{m-1}$。

  那么其他的点呢?当我们在算其中一个点的贡献的时候,这个点的贡献仅仅是问题转化之前的计算公式的一个分支,也就是说,我们可能会算到很多重复的情况,但在这些重复的情况中,我们只计算出来每个点的1的贡献,那么就不会在最后答案中出现算重的情况。

  这也解释了为什么贡献之间互不影响。

  进而,我们便可以算出其他的点的总的情况数$k^{n*m-n-m-1}$,其中$n*m-n-m-1$是除去这一行这一列的所有点,然后理解起来就很容易了。

  在不同的k_i的情况下,我们的所有点的贡献都是相同的,也是因为贡献互不影响。

  公式便有了 $$ans=n*m*\sum\limits _{i=0}^{k} {(i-1)}^{n-1}*{(i-1)}^{m-1}*k^{n*m-n-m-1}$$

  然后我们就愉快的A掉了这道题。

  小弟不才。

 

 1 #include<cstdio>
 2 #define LL long long
 3 #define HZOI std
 4 using namespace HZOI;
 5 const int mod=1e9+7;
 6 LL n,m,k;
 7 LL ans;
 8 inline LL Pow(LL ,LL );
 9 int main()
10 {
11     scanf("%lld%lld%lld",&n,&m,&k);
12     LL qt=Pow(k,(n*m-n-m+1)%(mod-1))%mod;
13     for (int i=1; i<=k; ++i)
14         ans=(ans+Pow(i-1,n-1)%mod*Pow(i-1,m-1)%mod*qt%mod)%mod;
15     printf("%lld\n",ans*n%mod*m%mod);
16     return 0;
17 }
18 inline LL Pow(LL x,LL y)
19 {
20     LL res=1;
21     while (y)
22     {
23         if (y&1) res=res*x%mod;
24         x=x*x%mod;
25         y>>=1;
26     }
27     return res;
28 }
chinese

T2 physics

  emmmmm......

  二维前缀和+暴力修改+二分答案。

  O(nmqlogn)。

  上天的复杂度。

  可是加上剪枝即可AC,原因不明。

  就是判一下我搞的这个点在不再最大的正方形里……

  

 1 #include<cstdio>
 2 #define LL long long
 3 #define HZOI std
 4 using namespace HZOI;
 5 const int N=1e3+5;
 6 LL n,m,Q;
 7 LL a[N][N],sm[N][N],maxx[3][3];
 8 inline LL read();
 9 inline LL min(int a,int b) {return a<b?a:b;}
10 int main()
11 {
12 //    freopen("physics3.in","r",stdin);
13 //    freopen("2.out","w",stdout);
14     n=read(),m=read(),Q=read();
15     for (int i=1,t=1; i<=n; ++i,t=1)
16     {
17         a[i][t]=getchar();
18         while ((a[i][t]^'+') && (a[i][t]^'-')) a[i][t]=getchar();
19         while ((a[i][t]=='+') || (a[i][t]=='-')) a[i][++t]=getchar();
20     }
21     maxx[0][0]=-1;
22     for (int q=1,x,y; q<=Q; ++q)
23     {
24         x=read(),y=read();
25         a[x][y]='-';
26         if (maxx[0][0]!=-1 && (maxx[1][1]>x || maxx[2][1]<x || maxx[1][2]>y || maxx[2][2]<y))
27             {printf("%lld\n",maxx[0][0]);continue;}
28         for (int i=1; i<=n; ++i)
29             for (int j=1; j<=m; ++j)
30             {
31                 sm[i][j]=0;
32                 sm[i][j]=sm[i][j-1]+sm[i-1][j]-sm[i-1][j-1];
33                 if (a[i][j]=='-') ++sm[i][j];
34             }
35         LL l=0,r=min(n,m),nw[3][3],stop=0;
36         while (l^r)
37         {
38             int mid=(l+r>>1)+1,yn=0;
39             for (int i=1; i+mid-1<=n; ++i)
40             {
41                 for (int j=1; j+mid-1<=m; ++j)
42                 {
43                     if (a[i][j]=='-' || a[i+mid-1][j+mid-1]=='-') continue;
44                     LL num=sm[i+mid-1][j+mid-1]-sm[i+mid-1][j-1]-sm[i-1][j+mid-1]+sm[i-1][j-1];
45                     if (!num) {yn=1;nw[1][1]=i,nw[1][2]=j,nw[2][1]=i+mid-1,nw[2][2]=j+mid-1;break;}
46                 }
47                 if (yn) break;
48             }
49             if (yn) l=mid; else r=mid-1;
50         }
51         printf("%lld\n",l);
52         maxx[0][0]=l;
53         for (int i=1; i<=2; ++i)
54             for (int j=1; j<=2; ++j)
55                 maxx[i][j]=nw[i][j];
56     }
57     return 0;
58 }
59 inline LL read()
60 {
61     LL nn=0; char cc=getchar();
62     while (cc<'0' || cc>'9') cc=getchar();
63     while (cc>='0' && cc<='9') nn=(nn<<3)+(nn<<1)+(cc^48),cc=getchar();
64     return nn;
65 }
physics

 

  正解待更。

 

 

 

posted @ 2019-08-29 11:55  _LH  阅读(180)  评论(0编辑  收藏  举报