codeforces原题链接
大佬题解
B - Binary Tree
每个人每次一定拿走奇数(2k−12^k-12k−1)个节点,如果先手必胜不难发现两人轮流拿最终一定拿奇数次(每次奇数个节点)说明一共有奇数个节点,如果先手必败说明最终两人共拿偶数次说明有偶数个节点,因此可以根据奇偶性判断输赢。
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=50010;
const ll mod=998244353;
int n;
int main()
{IO;int T=1;cin>>T;while(T--){cin>>n;for(int i=1;i<n;i++){int a,b;cin>>a>>b;}if(n&1) cout<<"Alice\n";else cout<<"Bob\n";}return 0;}
D - Defining Labels
模拟一下就即可。
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=50010;
const ll mod=998244353;
int main()
{IO;int T=1;cin>>T;while(T--){int k;ll x;cin>>k>>x;ll base=1,s=0;while(s<x){base=base*k;s+=base;}x-=s-base;base/=k;vector<int> ans;while(x>0&&base){int r=(x+base-1)/base;ans.push_back(r+9-k);x-=(r-1)*base; base/=k;}for(auto t:ans) cout<<t;cout<<'\n';}return 0;}
G - Game Design
本来想着构造一条链,不过发现kkk有点大搞不了,于是。。就没有于是了
参考上述题解发现自己还是对递归不熟练。
如果当前节点的方案数为偶数,那么我们构造两个方案数分别为 2,n22,\frac n 22,2n 的子节点;如果是奇数就构造两个方案数分别为
2,n22,\frac n 22,2n 的子节点,并且根节点单独作为一种方案,递归终点是k≤2k≤2k≤2 的时候,我们只需要建一条链即可。
当父节点的权值等于孩子节点的权值和的时候,父节点即可单独称为一种方案,如果大于就不能单独称为一种方案。
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=50010;
const ll mod=998244353;
int k,cnt;
int fa[N],c[N];
int dfs(int k,int p)
{int now=++cnt;fa[now]=p;if(k<=2){fa[++cnt]=now;c[cnt]=1;c[now]=3-k;return 1;}c[now]=dfs(k/2,now)+dfs(2,now)+(k%2==0);return c[now]-(k%2==0);}
int main()
{IO;int T=1;//cin>>T;while(T--){cin>>k;dfs(k,0);cout<<cnt<<'\n';for(int i=2;i<=cnt;i++) cout<<fa[i]<<' ';cout<<'\n';for(int i=1;i<=cnt;i++) cout<<c[i]<<' ';cout<<'\n';}return 0;}
E - Erasing Numbers
大佬题解
直接贴贴大佬题解的图片吧真的非常妙
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=5010;
const ll mod=998244353;
int a[N],n;
bool check(int x)
{int cnt0=0,cnt1=0;for(int i=1;i<=n;i++) cnt0+=a[i]<x,cnt1+=a[i]>x;if(cnt0==cnt1) return 1;else if(cnt0<cnt1){int cnt=0;for(int i=1;i<=n;i++){if(a[i]>x) cnt++;else if(a[i]==x) cnt=0;//最后消xelse cnt=max(cnt-1,0);if(cnt==3){cnt1-=2,cnt=1;if(cnt0==cnt1) return 1;}}}else {int cnt=0;for(int i=1;i<=n;i++){if(a[i]<x) cnt++;else if(a[i]==x) cnt=0;//最后消xelse cnt=max(cnt-1,0);if(cnt==3) {cnt0-=2,cnt=1;if(cnt0==cnt1) return 1;}}}return 0;}
int main()
{IO;int T=1;cin>>T;while(T--){cin>>n;for(int i=1;i<=n;i++) cin>>a[i];for(int i=1;i<=n;i++){if(check(a[i])) cout<<1;else cout<<0;}cout<<'\n';}return 0;}
J - Junior Mathematician
竟然还有点卡常,少了几个%就A了。
为了补这个题重学数位dp,然后发现基本的数位dp
// 2652 ms
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=5010;
const ll mod=1e9+7;
int a[N];
char l[N],r[N];
int m;
int f[N][65][65][2];
int ten[N];
int dfs(int pos,int s,int cur,bool limit)
{if(!pos) return cur==0;if(f[pos][s][cur][limit]!=-1) return f[pos][s][cur][limit];int v=limit?a[pos]:9;ll res=0;for(int i=0;i<=v;i++)res+=dfs(pos-1,(s+i)%m,((cur+s*i-i*ten[pos-1])%m+m)%m,limit&&i==v);res=(res%mod+mod)%mod;return f[pos][s][cur][limit]=res;
}
int solve(char s[])
{int cnt=strlen(s);// 初始化记忆化数组for(int i=1;i<=cnt;i++)for(int j=0;j<m;j++)for(int k=0;k<m;k++)f[i][j][k][0]=f[i][j][k][1]=-1;for(int i=1;i<=cnt;i++) a[i]=s[cnt-i]-'0';return dfs(cnt,0,0,1);
}
int main()
{IO;int T=1;cin>>T;while(T--){cin>>l+1>>r+1;cin>>m;ten[0]=1;for(int i=1;i<=5000;i++) ten[i]=ten[i-1]*10%m;// [l,r] 差分-> [0,r]-[0,l-1] 首先让l-1for(int i=strlen(l+1);i;i--){if(l[i]>'0') {l[i]--;break;}else l[i]='9';}cout<<((solve(r+1)-solve(l+1))%mod+mod)%mod<<'\n';}return 0;}
最近作业巨难,信号+数电,感觉老师上课疯狂划水,真就自学???
而且最近题解质量真的差,没时间打markdown不想打
要加油哦~