CF1485X Codeforces Round #701

D Multiples and Power Differences (構造)

給一個n*m的矩陣a,a[i][j]在1到16之間。現在要構造矩陣b,需要滿足如下條件:

1.b[i][j]在1到1e6之間

2.b[i][j]是a[i][j]的倍數

3.對於矩陣中任意相鄰的兩個數,要求存在正整數k,他們的差值絕對值等於k的四次方,不要求所有對的k都相同

構造神仙題,乍一看不可做。。

考慮第二個條件,由於a最多到16,發現1到16所有數的最小公倍數是$720720$!小於1e6。

在考慮第三個條件,可以對b矩陣黑白染色,黑點構造成$720720+a[i][j]^{4}$,白點是$720720$

矩陣問題不僅可以建邊跑圖論,還可以染色處理

 1 const int N1=505; const int maxn=720720;
 2 
 3 int n,m;
 4 int a[N1][N1],b[N1][N1];
 5 
 6 int main()
 7 {
 8     freopen("a.in","r",stdin);
 9     scanf("%d%d",&n,&m);
10     for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&a[i][j]);
11     for(int i=1;i<=n;i++,puts("")) for(int j=1;j<=m;j++) 
12     {
13         if((i+j)%2==0){
14             b[i][j]=maxn;
15         }else{
16             b[i][j]=maxn+a[i][j]*a[i][j]*a[i][j]*a[i][j];
17         }
18         printf("%d ",b[i][j]);
19     }
20     return 0;
21 }
View Code

 

F Copy or Prefix Sum (線段樹優化DP)

給定數組b,現在求有多少滿足如下條件的a數組:

$b[i]=a[i]$或$b[i]=\sum_{j=1}^{i}a[j]$

考場上最後一分鐘調出來了,結果我非得給數組多按個0然後CE(MLE)了。。不然就不會掉分了

發現第二個條件是前綴和比較特殊,並且第一個條件不影響答案

考慮DP選擇第二個條件的位置

定義f[i]表示i位置滿足第二個條件且不滿足第一個條件時的方案數

不滿足第一個條件時$b[i]\ne a[i]$,計算可得$sum[i-1]-sum[j-1]\ne 0$

$f[i]=\sum_{j=1}^{i-1}f[j](sum[i-1]\ne sum[j-1])$

線段樹優化DP就好了!又由於sum值域較大且可能爲負,動態開點+整體往右挪

 1 const int N1=200005; const int inf=0x3f3f3f3f;
 2 const ll maxn=1e15;
 3 const int p=1000000007;
 4 
 5 int T,n;
 6 int a[N1],b[N1];
 7 ll f[N1];
 8 struct SEG{
 9 ll sum[N1*65]; int ls[N1*65],rs[N1*65],tot;
10 void pushup(int rt){ sum[rt]=(sum[ls[rt]]+sum[rs[rt]])%p; }
11 void upd(ll x,ll l,ll r,int &rt,ll w)
12 {
13     if(!rt) rt=++tot;
14     if(l==r){ (sum[rt]+=w)%=p; return; }
15     ll mid=(l+r)>>1;
16     if(x<=mid) upd(x,l,mid,ls[rt],w);
17     else upd(x,mid+1,r,rs[rt],w);
18     pushup(rt);
19 }
20 ll query(ll L,ll R,ll l,ll r,int rt)
21 {
22     if(!rt) return 0;
23     if(L<=l&&r<=R) return sum[rt];
24     ll mid=(l+r)>>1; ll ans=0;
25     if(L<=mid) ans+=query(L,R,l,mid,ls[rt]);
26     if(R>mid) ans+=query(L,R,mid+1,r,rs[rt]);
27     ans%=p;
28     return ans;
29 }
30 void clr()
31 {
32     while(tot) sum[tot]=0, ls[tot]=rs[tot]=0, tot--;    
33 }
34 }s;
35 ll sum[N1];
36 
37 int main()
38 {
39     scanf("%d",&T);
40     ll ans=0,mi=maxn,ma=-maxn;
41     while(T--)
42     {
43         scanf("%d",&n); 
44         for(int i=1;i<=n;i++) scanf("%d",&b[i]), sum[i]=sum[i-1]+b[i], mi=min(mi,sum[i]), ma=max(ma,sum[i]);
45         ll ans=1; f[1]=0; int root=0;
46         for(int i=2;i<=n;i++)
47         {
48             // f[i]=1;
49             if(sum[i-1]!=0) f[i]=1; else f[i]=0;
50             // for(int j=1;j<i;j++) if(sum[i-1]!=sum[j-1])
51             //     (f[i]+=f[j])%=p;
52             if(mi<sum[i-1]) (f[i]+=s.query(mi+maxn,sum[i-1]+maxn-1,mi+maxn,ma+maxn,root));
53             if(sum[i-1]<ma) (f[i]+=s.query(sum[i-1]+maxn+1,ma+maxn,mi+maxn,ma+maxn,root));
54             f[i]%=p;
55             s.upd(sum[i-1]+maxn,mi+maxn,ma+maxn,root,1ll*f[i]);
56             (ans+=f[i])%=p;
57         }
58         printf("%lld\n",ans);
59         s.clr();
60     }
61     return 0;
62 }
View Code

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章