大概,接下來半年都不怎麼打比賽了(大哭)
這場比賽自己打得並不好,似乎也是冥冥中的必然吧。
先看C:
題意:在n*n上放置多米諾骨牌,不重疊,不要求全覆蓋。
對於每一行,我們記它的值爲在這一行的方塊上有覆蓋的多米諾骨牌的個數,列同理。我們要求這些數要相同,且至少放置一塊多米諾骨牌。
行的話輸出-1,不行的話輸出方案。
解法:3,4,5,7構造出來
3,4比較容易手玩,但5,7博主這垃圾水平,絕對玩不出來。
如果有讀者有算法方法,歡迎在下面評論。
然後4,5,7的時候構造滿足每行每列都是3。
於是我們得到了一個這樣的算法:
先特判是3的倍數的n
然後判可以表示成的n
然後你發現只有n=1,2會判成-1,顯然
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
int n;
#define Maxn 1005
bool f[Maxn];
int pre[Maxn];
char ch[Maxn][Maxn];
char c3[10][10]={
{'a','a','.'},
{'.','.','a'},
{'.','.','a'}
};
char c4[10][10]={
{'a','a','b','c'},
{'d','d','b','c'},
{'b','c','a','a'},
{'b','c','d','d'}
};
char c5[10][10]={
{'a','a','b','b','a'},
{'b','c','c','.','a'},
{'b','.','.','c','b'},
{'a','.','.','c','b'},
{'a','b','b','a','a'}
};
char c7[10][10]={
{'a','a','b','b','c','c','.'},
{'d','d','.','d','d','.','a'},
{'.','.','d','.','.','d','a'},
{'.','.','d','.','.','d','b'},
{'d','d','.','d','d','.','b'},
{'.','.','d','.','.','d','c'},
{'.','.','d','.','.','d','c'}
};
inline void output(){
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j)printf("%c",ch[i][j]);
puts("");
}
}
int main(){
scanf("%d",&n);
f[0]=true;
for(int i=1;i<=n;++i){
if(i>=4&&f[i-4]){
f[i]=true;
pre[i]=4;
}
if(i>=5&&f[i-5]){
f[i]=true;
pre[i]=5;
}
if(i>=7&&f[i-7]){
f[i]=true;
pre[i]=7;
}
}
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)ch[i][j]='.';
if(n%3==0){
for(int i=1;i<=n;i+=3)
for(int j=0;j<3;++j)
for(int k=0;k<3;++k)
ch[i+j][i+k]=c3[j][k];
output();
}else if(f[n]){
int tmp=n;
while(n){
if(pre[n]==4){
for(int i=n-3;i<=n;++i)
for(int j=n-3;j<=n;++j)
ch[i][j]=c4[i-n+3][j-n+3];
}
if(pre[n]==5){
for(int i=n-4;i<=n;++i)
for(int j=n-4;j<=n;++j)
ch[i][j]=c5[i-n+4][j-n+4];
}
if(pre[n]==7){
for(int i=n-6;i<=n;++i)
for(int j=n-6;j<=n;++j)
ch[i][j]=c7[i-n+6][j-n+6];
}
n-=pre[n];
}
n=tmp;
output();
}else puts("-1");
return 0;
}
D:
問有多少個長度爲n的序列滿足一下條件
且
且
解法
不妨我們弄出一個新序列,在A的基礎上構造
令
好嘞,這要求爲正,後面的爲非負,且總和不超過n
再來考慮一下如何滿足第二個條件
我們發現,當滿足的時候,所有n都會滿足
那考慮滿足的時候b需要滿足些什麼
寫成不等式,展開,化簡,得到
其中的係數讀者自行得到,非負
當然,還有另一個不等式是我們需要滿足的
於是,當確定以後,的取值有個,當然負數就不能算上貢獻了
於是,很容易想到,對右邊的式子dp一下即可
考慮一下正確性
只要我們保證了過程中非負
且只枚舉時的貢獻
的取值也是會大於0的
沒錯
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,Mod;
#define Maxn 5005
int ans[Maxn],a[Maxn];
int main(){
scanf("%d%d",&n,&Mod);
if(n&1){
int k=(n-1)/2+1;
for(int i=0;i<=k-2;++i)a[2+i]=i;
for(int i=k-1,j=1;i>=1;--i,++j)a[k+j]=i;
}else{
int k=n/2;
for(int i=0;i<=k-2;++i)a[2+i]=i;
a[k+1]=k-1;
for(int i=k-1,j=1;i>=1;--i,++j)a[k+1+j]=i;
}
for(int i=2;i<=n;++i)a[i]++;
ans[0]=1;
for(int i=2;i<=n;++i){
for(int j=a[i];j<n;++j){
ans[j]+=ans[j-a[i]];
if(ans[j]>=Mod)ans[j]-=Mod;
}
}
int Ans=0;
for(int i=0;i<n;++i)Ans=(Ans+1ll*(n-i)*ans[i])%Mod;
printf("%d\n",Ans);
return 0;
}
E:
題意有點複雜了,不想說
解法
T=1:考慮枚舉w,並且判斷它可不可以。
我們從右向左加入balancer,並且動態維護一個長度爲n的布爾數組B。表示當前i出發,最後會不會停止在w。一開始,只有
假設我們當前從右往左加入到了x和y
那麼顯然,爲了讓更多的出發點最後集中在w
會變成,定方向的方法很好像
如果我們每個w都進行一遍這個過程,顯然不太好
bitset壓位!
維護n的長度爲n的bitset
其中表示當w=j時,當前時刻從i出發,會不會終止在j
初始
每次只需要
最後對去個交即可
T=2:小清新的構造
首先n=2的時候肯定不行
考慮n>2的時候,我們證明它一定有方案
同樣是從右到左加入
維護一個整數數組,長度爲n,其中表示i此刻出發的話,最後到達哪裏
只要我們保證B每時每刻都會有兩個不同的值即可
初始時顯然滿足
無所謂
如果在B中出現了至少兩次,那麼令
如果在B中出現了至少兩次,同上
如果都只出現了一次,隨意,然後因爲n>2,所以還存在一個既不等於,也不等於的值
不同的值保證了至少存在兩個
#include<iostream>
#include<cstring>
#include<cstdio>
#include<bitset>
#include<algorithm>
using namespace std;
int n,m,T;
#define Maxn 50010
int x[Maxn<<1],y[Maxn<<1];
bitset<Maxn> b[Maxn];
bool ap[Maxn];
int seq[Maxn<<1];
int to[Maxn],B[Maxn];
inline void rd(int &x){
x=0;char ch=getchar();
while(ch<'0'||ch>'9')ch=getchar();
while(ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
}
int main(){
rd(n);rd(m);rd(T);
for(int i=1;i<=m;++i){
rd(x[i]);rd(y[i]);
}
if(T==1){
for(int i=1;i<=n;++i)b[i][i]=1;
bitset<Maxn> res;
for(int i=m;i>=1;--i){
res=b[x[i]]|b[y[i]];
b[x[i]]=b[y[i]]=res;
}
res=b[1];
for(int i=2;i<=n;++i)res&=b[i];
int flag=-1;
for(int i=1;i<=n;++i)
if(res[i]){
flag=i;
break;
}
if(flag==-1){
puts("-1");
return 0;
}
ap[flag]=true;
for(int i=m;i>=1;--i){
if(ap[x[i]]==false&&ap[y[i]]==false)seq[i]=0;
else if(ap[x[i]]==true&&ap[y[i]]==true)seq[i]=0;
else if(ap[x[i]])seq[i]=0;
else seq[i]=1;
bool tmp=ap[x[i]]|ap[y[i]];
ap[x[i]]=ap[y[i]]=tmp;
}
for(int i=1;i<=m;++i)
if(seq[i]==0)printf("^");
else printf("v");
}else{
if(n==2){
puts("-1");
return 0;
}
for(int i=1;i<=n;++i){
B[i]=i;
to[i]=1;
}
for(int i=m;i>=1;--i){
if(B[x[i]]==B[y[i]]){
seq[i]=0;
continue;
}
if(to[B[x[i]]]>=2){
seq[i]=1;
to[B[x[i]]]--;
B[x[i]]=B[y[i]];
to[B[y[i]]]++;
}else{
seq[i]=0;
to[B[y[i]]]--;
B[y[i]]=B[x[i]];
to[B[x[i]]]++;
}
}
for(int i=1;i<=m;++i)
if(seq[i]==0)printf("^");
else printf("v");
}
return 0;
}