總結
第二次比賽在配合與節奏上稍微比第一次有了較大的進步,所謂一回生二回熟,大概就是這樣吧。但是,問題同樣很明顯,首先就我而言1、我打題的準確率不夠高,一道題要重複交好幾遍,即使我知道這只是碰運氣……2、算法能力較差,有點拖累了隊友的感覺 3、代碼實現能力仍有待加強
Rikka with Nash Equilibrium (dp)
description
給定n,m(<80),求一個滿足納什平衡點只有一個的矩形,一個點是納什平衡當且僅當:
solution
看到題目dp走起,我們從大到小開始放數,設f[k][i][j]表示當前排了i行j列,佔用了其中k個位置,f[k][i][j]可轉移至f[k+1][i][j],f[k+1][i+1][j],f[k+1][i][j+1]分別表示放入原矩陣i*j,新開一行或新開一列,由於都是從大到小放,而且新開得到行列都基於原來的行列,故納什平衡點不會增加
code
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define rp(i,a,b) for(int i=a;i>=b;i--)
#define max(a,b) ((a>b)?a:b)
#define min(a,b) ((a<b)?a:b)
#define ll long long
using namespace std;
ll dp[85][85][2];
int main()
{
ll n,m,mo;
int t;
scanf("%d",&t);
while(t--)
{
scanf("%lld%lld%lld",&n,&m,&mo);
memset(dp,0,sizeof(dp));
dp[1][1][1]=n*m%mo;
int flag=1;
ll ans=0;
for(ll k=2;k<=n*m;k++)
{
flag=1-flag;
for(ll i=1;i<=n;i++)
{
for(ll j=1;j<=m;j++)
{
dp[i][j][flag]=0;
if(k>i*j)continue;
dp[i][j][flag]=dp[i][j][1-flag]*(i*j-k+1)%mo;
dp[i][j][flag]=(dp[i][j][flag]+dp[i-1][j][1-flag]*(n-i+1)%mo*j)%mo;
dp[i][j][flag]=(dp[i][j][flag]+dp[i][j-1][1-flag]*(m-j+1)%mo*i)%mo;
if(k==n*m)ans=(ans+dp[i][j][flag])%mo;
}
}
}
printf("%lld\n",ans);
}
}
B Rikka with Seam (dp)
description
給出一個n*m(<2e3)的01矩陣,要求計算每行選擇一個位置刪除後構成的不同矩陣的數量,相鄰行選擇刪除的位置不能相差k
solution
設f[i][j]表示刪除i行第j個數造成的不同矩陣的個數,g[i][j]表示刪除i行第j個數造成的與刪除第j-1個數造成的01矩陣完全相同的數量,當a[i][j]!=a[i][j-1]時,g[i][j]=0。前綴和優化一下即可。
code
#include<bits/stdc++.h>
using namespace std;
const int mo=998244353;
int t,n,m,k;
char s[2010][2010];
long long dp1[2010][2010],dp2[2010][2010];
int main(){
for(int i=0;i<=2000;i++) dp1[1][i]=i;
for(int i=1;i<=2000;i++) dp1[i][0]=dp2[i][0]=0;
cin>>t;
while(t--){
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++) scanf("%s",s[i]);
for(int i=1;i<m;i++)
if(s[1][i]==s[1][i-1]) dp2[1][i+1]=1;
else dp2[1][i+1]=0;
dp2[1][1]=0;
for(int i=1;i<=m;i++) dp2[1][i]+=dp2[1][i-1];
for(int i=2;i<=n;i++){
for(int j=1;j<=m;j++){
dp1[i][j]=(dp1[i-1][min(j+k,m)]-dp1[i-1][max(j-k-1,0)]-(dp2[i-1][min(j+k,m)]-dp2[i-1][max(j-k,0)])+2*mo)%mo;
if(j>=2&&s[i][j-1]==(s[i][j-2])) dp2[i][j]=(dp1[i-1][min(j+k-1,m)]-dp1[i-1][max(j-k-1,0)]-(dp2[i-1][min(j+k-1,m)]-dp2[i-1][max(j-k,0)])+2*mo)%mo;
else dp2[i][j]=0;
}
for(int j=1;j<=m;j++){
dp1[i][j]=(dp1[i][j]+dp1[i][j-1]+mo)%mo;
dp2[i][j]=(dp2[i][j-1]+dp2[i][j]+mo)%mo;
}
}
long long ans=(dp1[n][m]-dp2[n][m]+mo)%mo;
cout<<ans<<endl;
}
return 0;
}
D Rikka with Stone-Paper-Scissors (數學題 結論題)
description
有兩個人在玩石頭剪刀布,小A有a,b,c個剪刀石頭布,小B有A,B,C個剪刀石頭布(a+b+c=A+B+C),小A每次隨機出,小B可以透視到小A目前有的牌後選擇性的出牌。每輪贏者得一分,輸者扣一分,問小B的期望得分。
solution
不知道那羣大哥是怎麼隨手寫結論的,反正awsl,設f[n][a][b][A][B]表示當前情況的期望,我們假設c最大,那麼小B每次肯定出A
我們假設(別問我怎麼來的 ),那麼f[1]成立,若f[n]成立,推得f[n+1]也成立,故結論成立
code
#include<bits/stdc++.h>
using namespace std;
const long long mo=998244353;
long long gcd(long long x,long long y){
return y?gcd(y,x%y):x;
}
int main(){
long long q,n,m,t,a,b,c,a1,b1,c1;
cin>>t;
while(t--){
cin>>a>>b>>c>>a1>>b1>>c1;
n=a1*(c-b)+b1*(a-c)+c1*(b-a);
m=a+b+c;
q=gcd(abs(n),m);
n/=q;
m/=q;
if(m==1||n==0) cout<<n<<endl;
else cout<<n<<"/"<<m<<endl;
}
return 0;
}
J Rikka with Time Complexity(模擬)
description
Let fa(n)=log…logn (there are exactly a log in this function, and log uses base 2). And then, for an integer array A, Rikka defines gA(n) in the following way (B is the suffix of A with length |A|−1):
For example, and .
Now, given integer arrays A and B, Rikka wants you to compare gA(n) with gB(n). i.e., let k be limn→+∞gA(n)gB(n). If k=0, output −1; if k=+∞, output 1; otherwise output 0.m<=2000)( the length of A and B. <=3)
solution
我們發現那就很舒服了,我們直接用這種方式展開式子後從小到大排序比較即可。
code
#include<bits/stdc++.h>
using namespace std;
const int N=5;
int read(){
int f=1,s=0;char c=getchar();
for(;c<'0'||c>'9';c=getchar())if(c=='0')f=-1;
for(;c>='0'&&c<='9';c=getchar())s=s*10+c-48;
return f*s;
}
const int oo=0x3f3f3f3f;
struct pp{
int x,y;
pp(int x_,int y_){
x=x_;y=y_;
if(x>y)swap(x,y);
}
};
int cmp(pp a,pp b){
if(a.x<b.x)return 1;
if(a.x>b.x)return -1;
if(a.y<b.y)return 1;
if(a.y>b.y)return -1;
return 0;
}
struct qq{
int a[N];
int len;
void in(){
for(int i=1;i<=len;i++)a[i]=read();
for(int i=len+1;i<=3;i++)a[i]=oo;
}
}a,b;
int work(){
a.len=read();b.len=read();
a.in();b.in();
pp t1{a.a[1]+2,oo};
pp t2{a.a[2]+1,a.a[3]};
pp t3{b.a[1]+2,oo};
pp t4{b.a[2]+1,b.a[3]};
if(cmp(t1,t2)==-1)swap(t1,t2);
if(cmp(t3,t4)==-1)swap(t3,t4);
if(cmp(t1,t3))return cmp(t1,t3);
else return cmp(t2,t4);
}
int main(){
int T=read();
while(T--){
printf("%d\n",work());
}
return 0;
}
K Rikka with Badminton (數學題)
description
打羽毛球,設a個人只有啥都沒有,b人只有拍,c個人只有球,d個人有球有拍,現在要挑一些人加入一個社團,要求這些人中至少有兩個人有拍,1個人有球,問組建失敗的方案數。
solution
話說好險你們不在我們村,有人帶拍不帶球,有人帶球不帶拍,還有人啥都不帶,有這麼打羽毛球的嗎!
這不是高中數學題嗎?我們枚舉有球有拍的人的個數,當有0人時方案爲最後答案乘上即可
code
#include<bits/stdc++.h>
using namespace std;
const long long mo=998244353;
int mi(long long x,long long k){
int ans=1;
while(k!=0){
if(k%2==1) ans=ans*x%mo;
x=x*x%mo;
k=k/2;
}
return ans%mo;
}
int main(){
long long t,a,b,c,d;
cin>>t;
while(t--){
cin>>a>>b>>c>>d;
cout<<((1+b+d)%mo*mi(2,c)%mo+mi(2,b)%mo-(1+b)%mo)%mo*mi(2,a)%mo<<endl;
}
return 0;
}