C、小w和大W的決鬥
博弈論
sg函式打表即可
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define int ll
#define endl '\n'
#define fi first
#define se second
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
#define lyh(i,a,b) for(int i=a;i<b;i++)
#define hyl(i,a,b) for(int i=a;i>b;i--)
typedef pair<int,int> PII;
typedef unsigned long long ull;
const int ddx[8]={-1, 0, 1, 0, 1, -1, 1, -1};
const int ddy[8]={0, 1, 0, -1, -1, 1, 1, -1};
const int INF=0x3f3f3f3f;
const int N=2e5+10;
const int M=1010;
int n,m;
int mod,fa[N];
int Fpow(int b,int p){long long res=1;for(;p;p>>=1,b=b*b%mod)if(p&1)res=res*b%mod;return res;}
int qmi(ll a,ll k,ll p){ll res = 1;while (k) {if (k&1) res = res * a % p; k >>= 1;a = a * a % p;}return res;}
void init() {for(int i=1;i<=n;i++) fa[i]=i;}
int find(int x) {return fa[x]==x?x:fa[x]=find(fa[x]);}
void add(int a,int b) {int x=find(a);int y=find(b);fa[x]=y;}
bool ask(int a,int b) {return find(a)==find(b);}
int a[N];
vector<int>f(105,-1);
int sg(int x)
{
if(f[x]!=-1) {
return f[x];
}
set<int>st;
for(int i=1;i<=x;i++) //操作一
{
st.insert(sg(x-i));
}
for(int i = 1;i<x-2;i++) //操作二
{
for(int j = 1;i+j<x;j++)
{
st.insert(sg(i)^sg(j)^sg(x-i-j));
}
}
for(int i=0;;i++)
{
if(!st.count(i)) return f[x] = i;
}
}
void solve()
{
cin>>n;
int ans = 0;
for (int i = 1;i <= n;i ++)
{
int x;
cin >> x;
ans ^= sg(x);
}
if(ans>0){
cout<<"w win"<<endl;
return;
}else{
cout<<"W win"<<endl;
return;
}
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
int t=1;
//cin >> t;
while(t--) {
solve();
}
return 0;
}
D、A*BBBB
題解中說:模擬乘法發現,當B每一位相同時假設為x,那麼就是A乘x,然後B有多少位就往前移多少次,然後再用字首和進行維護當前位數為多少。
我們首先舉一個例子:114514 與 22222 相乘
114514*2 = 229028
114514 與 22222 相乘
1 1 4 5 1 4
x 2 2 2 2 2
--------------------
2 2 9 0 2 8
2 2 9 0 2 8
2 2 9 0 2 8
2 2 9 0 2 8
2 2 9 0 2 8
---------------------
我們都知道,答案的總長度是|a|+|b|
相乘結果的每一列都是一個區間
用l和r表達這個區間,並用字首和和差分計算即可
8
2 8
0 2 8
9 0 2 8
2 9 0 2 8
2 2 9 0 2
2 2 9 0
2 2 9
2 2
2
code:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define int ll
#define endl '\n'
#define fi first
#define se second
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
#define lyh(i,a,b) for(int i=a;i<b;i++)
#define hyl(i,a,b) for(int i=a;i>b;i--)
typedef pair<int,int> PII;
typedef unsigned long long ull;
const int ddx[8]={-1, 0, 1, 0, 1, -1, 1, -1};
const int ddy[8]={0, 1, 0, -1, -1, 1, 1, -1};
const int INF=0x3f3f3f3f;
const int N=5e6+10;
const int M=1010;
int n,m;
int mod,fa[N];
int Fpow(int b,int p){long long res=1;for(;p;p>>=1,b=b*b%mod)if(p&1)res=res*b%mod;return res;}
int qmi(ll a,ll k,ll p){ll res = 1;while (k) {if (k&1) res = res * a % p; k >>= 1;a = a * a % p;}return res;}
void init() {for(int i=1;i<=n;i++) fa[i]=i;}
int find(int x) {return fa[x]==x?x:fa[x]=find(fa[x]);}
void add(int a,int b) {int x=find(a);int y=find(b);fa[x]=y;}
bool ask(int a,int b) {return find(a)==find(b);}
string a,b;
int pr[N];
void solve()
{
cin>>a>>b;
if(a[0]=='0'||b[0]=='0'){
cout<<0<<endl;
return;
}
reverse(a.begin(),a.end()); //乘法是從個位開始向前計算的
vector<int>v;
int B = b[0]-'0';
int t = 0;
for (int i = 0; i < a.size(); i ++ ) //計算A與B【0】的乘積
{
t += (a[i]-'0')*B;
v.push_back(t % 10);
t /= 10;
}
while(t)
{
v.push_back(t % 10);
t /= 10;
}
reverse(v.begin(),v.end());
//求字首和
//這裡從1開始記錄,方便計算
for(int i=1;i<=v.size();i++)
{
pr[i] = pr[i-1]+v[i-1];
}
int n = v.size();
int m = b.size();
int p = 0;
vector<int>ans;
for(int i =1;i<=n+m-1;i++) //模擬A與BBB……相乘的加法
{
int l =max(0ll,n-i);
int r = min(n,n+m-i);
p += pr[r]-pr[l];
ans.push_back(p%10);
p/=10;
}
while(p){
ans.push_back(p%10);
p/=10;
}
reverse(ans.begin(),ans.end());
for(int i=0;i<ans.size();i++) cout<<ans[i];
cout<<endl;
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
int t=1;
cin >> t;
while(t--) {
solve();
}
return 0;
}
E、“好”字元
這題考察了字串雜湊
字串雜湊模板:
核心思想:將字串看成P進位制數,P的經驗值是131或13331,取這兩個值的衝突機率低
小技巧:取模的數用2^64,這樣直接用unsigned long long儲存,溢位的結果就是取模的結果
typedef unsigned long long ULL;
ULL h[N], p[N]; // h[k]儲存字串前k個字母的雜湊值, p[k]儲存 P^k mod 2^64
// 初始化
p[0] = 1;
for (int i = 1; i <= n; i ++ )
{
h[i] = h[i - 1] * P + str[i];
p[i] = p[i - 1] * P;
}
// 計運算元串 str[l ~ r] 的雜湊值
ULL get(int l, int r)
{
return h[r] - h[l - 1] * p[r - l + 1];
}
操作1 :將字串複製並連線在結尾。
操作2 :將字串根據每個字元是否為字元 轉化為一個01串(或將字元x以外的字元全部轉化為特殊字元)
code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define int ll
#define endl '\n'
#define fi first
#define se second
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
#define lyh(i,a,b) for(int i=a;i<b;i++)
#define hyl(i,a,b) for(int i=a;i>b;i--)
typedef pair<int,int> PII;
typedef unsigned long long ull;
const int ddx[8]={-1, 0, 1, 0, 1, -1, 1, -1};
const int ddy[8]={0, 1, 0, -1, -1, 1, 1, -1};
const int INF=0x3f3f3f3f;
const int N=1e6+10;
const int M=1010;
int n,m;
int mod,fa[N];
int Fpow(int b,int p){long long res=1;for(;p;p>>=1,b=b*b%mod)if(p&1)res=res*b%mod;return res;}
int qmi(ll a,ll k,ll p){ll res = 1;while (k) {if (k&1) res = res * a % p; k >>= 1;a = a * a % p;}return res;}
void init() {for(int i=1;i<=n;i++) fa[i]=i;}
int find(int x) {return fa[x]==x?x:fa[x]=find(fa[x]);}
void add(int a,int b) {int x=find(a);int y=find(b);fa[x]=y;}
bool ask(int a,int b) {return find(a)==find(b);}
const ull P =131;
ull h1[N],h2[2*N],p[2*N];
void getb(string s,char c,ull* h) //初始化
{
for (int i = 1; i <s.size(); i ++ )
{
h[i] = h[i - 1] * P + (s[i] == c);
}
}
int get(ull *h,int l, int r) //計算雜湊值
{
return h[r] - h[l - 1] * p[r - l + 1];
}
string a,b;
void solve()
{
p[0]=1;
cin>>n;
cin>>a>>b;
set<char>st(a.begin(),a.end());
a=" "+a;
b=" "+b+b;
for(int i=1;i<N*2;i++)
{
p[i]=p[i-1]*P;
}
int ans = 0;
for(char c:st){
getb(a,c,h1);
getb(b,c,h2);
for(int i=1;i<=n;i++)
{
if(get(h2,i,i+n-1)==get(h1,1,n))
{
ans++;
break;
}
}
}
cout<<ans<<endl;
return;
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
int t=1;
//cin >> t;
while(t--) {
solve();
}
return 0;
}
G、lxy的通風報信
bfs+prim最短路
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define int ll
#define endl '\n'
#define fi first
#define se second
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
#define lyh(i,a,b) for(int i=a;i<b;i++)
#define hyl(i,a,b) for(int i=a;i>b;i--)
typedef pair<int,int> PII;
typedef unsigned long long ull;
const int ddx[8]={-1, 0, 1, 0, 1, -1, 1, -1};
const int ddy[8]={0, 1, 0, -1, -1, 1, 1, -1};
const int INF=0x3f3f3f3f;
const int N=2e5+10;
const int M=1010;
int n,m;
int mod,fa[N];
int Fpow(int b,int p){long long res=1;for(;p;p>>=1,b=b*b%mod)if(p&1)res=res*b%mod;return res;}
int qmi(ll a,ll k,ll p){ll res = 1;while (k) {if (k&1) res = res * a % p; k >>= 1;a = a * a % p;}return res;}
void init() {for(int i=1;i<=n;i++) fa[i]=i;}
int find(int x) {return fa[x]==x?x:fa[x]=find(fa[x]);}
void add(int a,int b) {int x=find(a);int y=find(b);fa[x]=y;}
bool ask(int a,int b) {return find(a)==find(b);}
char f[M][M];
int a[M][M];
int g[M][M];
int cnt = 0;
int ts = 1;
void bfs(int sx,int sy)
{
queue<PII>q;
q.push({sx,sy});
vector<vector<int>>dist(1010,vector<int>(1010,0));
vector<vector<int>>st(1010,vector<int>(1010,0));
dist[sx][sy]=0;
st[sx][sy]=1;
ts = 1;
while(!q.empty())
{
auto t = q.front();
q.pop();
int x = t.fi;
int y = t.se;
if(a[x][y]){
g[a[sx][sy]][a[x][y]]=dist[x][y];
}
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
{
int nx = x+ddx[i];
int ny = y+ddy[i];
if(st[nx][ny]||nx<1||nx>n||ny<1||ny>m||f[nx][ny]=='#') continue;
q.push({nx,ny});
st[nx][ny]=1;
if(f[nx][ny]=='*')
{
ts++;
}
dist[nx][ny] = dist[x][y]+1;
}
}
}
}
int prim()
{
vector<int>dis(1010,INF);
vector<int>vis(1010);
dis[1] = 0;
int res = 0;
for (int i =1;i<=cnt; i ++ )
{
int t = -1;
for (int j = 1; j <= cnt; j ++ )
if (!vis[j] && (t == -1 || dis[t] > dis[j]))
t = j;
res += dis[t];
vis[t] = true;
for (int j = 1; j <= n; j ++ ) dis[j] = min(dis[j], g[t][j]);
}
return res;
}
void solve()
{
cin>>n>>m;
rep(i,1,n)
{
rep(j,1,m)
{
cin>>f[i][j];
if(f[i][j] == '*')
{
a[i][j] = ++cnt;
}
}
}
rep(i,1,n)
{
rep(j,1,m)
{
if(a[i][j]){
bfs(i,j);
if(ts<cnt){
cout<<"No"<<endl;
return;
}
}
}
}
cout<<prim()<<endl;
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
int t=1;
//cin >> t;
while(t--) {
solve();
}
return 0;
}