2019山东省赛
A.ZOJ4113 Calandar
题意:
题目中一年有12个月,每个月都是30天,一周五天。现在给你一个日期和当天是星期几,要你求给出的第二个日期是星期几。
题解:
因为每个月都是30天,每周都是5天,所以每个月同一号对应的星期几都是相同的。比如1年1月1日是星期一,不管是哪年哪月的1号都是星期一。所以只要计算两个日期的日这一栏相差多少输出对应的星期几就行了。
代码:
#include <cstdio> #include <cstring> #define ll long long #define ull unsigned long long using namespace std; const int N = 200000 + 5; const ll INF = 1e18; int T; char xq[5][30] = {"Monday","Tuesday","Wednesday","Thursday","Friday"}; int main() { for (scanf("%d",&T); T--;) { int y1,m1,d1,y2,m2,d2; char s[30]; scanf("%d%d%d%s%d%d%d",&y1,&m1,&d1,s,&y2,&m2,&d2); int pos; for (int i = 0; i < 5; i++) { if (strcmp(xq[i],s) == 0) { pos = i; break; } } if (d1<=d2) { printf("%s ",xq[(pos+(d2-d1))%5]); }else { printf("%s ",xq[(pos+30 - (d1-d2))%5 ]); } } return 0; }
B.ZOJ4114 Flipping Game
题意:
有n个开关对应n盏灯,按顺序给出每盏灯的初始状态和目标状态,游戏有k轮,每轮可以按m个不同的开关各一次。问你方案数。
题解:
一看题就想到用组合数,但是没想好怎么计算。
我们可以用一个二维dp[i][j] ,表示第i轮有j个状态与目标状态不同的灯的方案数。每一轮我们可以选x个与目标状态不同的灯,y个与目标状态相同的灯:x ≤ j,y ≤ n-j,x+y = m,按了之后与目标状态不同的灯的数量为 j - x + y。
那么可以得到状态转移方程为:dp[i+1][j-x+y] = dp[i+1][j-x+y] + dp[i][j]*C(j,x)*C(n-j,y)
代码:
#include <cstdio> #include <cstring> #include <algorithm> #define ll long long #define ull unsigned long long using namespace std; const int N = 100 + 5; const ll mod = 998244353; const ll INF = 1e18; int T; char s1[N],s2[N]; ll inv[N],fac[N],inv_fac[N],dp[N][N]; void init() { inv[0]=inv[1]=inv_fac[0]=fac[0]=1; for(int i=2; i<N; i++) inv[i]=inv[mod%i]*(mod-mod/i)%mod; for(int i=1; i<N; i++) fac[i]=fac[i-1]*i%mod; for(int i=1; i<N; i++) inv_fac[i]=inv_fac[i-1]*inv[i]%mod; } ll C(int n,int m) { return fac[n]*inv_fac[m]%mod*inv_fac[n-m]%mod; } int main() { init(); for (scanf("%d",&T); T--;) { int n,m,k,num=0; scanf("%d%d%d%s%s",&n,&k,&m,s1,s2); for (int i = 0; i < n; ++i) { if(s1[i] != s2[i]) num++; } memset(dp,0,sizeof(dp)); dp[0][num] = 1; for (int i = 0; i < k; ++i) { for (int j = 0; j <= n; ++j) { if (!dp[i][j]) continue; for (int x = 0; x <= j; ++x) { int y = m - x; if (y<0||y>(n-j)) continue; dp[i+1][j-x+y] = (dp[i+1][j-x+y]+dp[i][j]*C(j, x)%mod*C(n-j,y)%mod)%mod; } } } printf("%lld ",dp[k][0]); } return 0; }