eg:好久不见的普及组题目,自信满满以为自己ak了,结果C题莫名被卡常(后来开了氧气优化就过了,我一直以为氧气优化评测机会自己开不用手动开),D题公式精度问题被卡,最后rk14,btw牛客一场上绿还是很高兴的嘿嘿嘿。
传送门
题意:统计一个字符串里有多少个不同的字符。
题解:map或者set随便搞。
#include
using namespace std;
typedef long long ll;
const int maxn=1e6+10;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
ll read(){
ll f=1,x=0;char ch;
do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
return f*x;
}
char s[maxn];
map<char,int>mp;
int main(){
scanf("%s",&s);
int len=strlen(s);
for(int i=0;i<len;i++)mp[s[i]] ++;
printf("%d\n",mp.size());
return 0;
}
题意:类似于统计水仙花数,一组1e6范围。
题解:读入一个判断一个即可。
#include
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
ll read(){
ll f=1,x=0;char ch;
do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
return f*x;
}
int n,ans;
ll quick(ll a,int b){
ll res=1;
while(b){
if(b&1)res=res*a;
a=a*a;
b>>=1;
}
return res;
}
bool check(ll x){
ll res=0,t=0,xx=x;
while(xx){
t++;
xx/=10;
}
xx=x;
while(x){
ll k=x%10;
res+=quick(k,t);
x/=10;
}
if(res==xx)return true;
return false;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
ll x;
scanf("%lld",&x);
if(check(x))ans++;
}
printf("%d\n",ans);
return 0;
}
题意:给出一颗无根树,让你确定他的根,使得深度之和最小。
题解:没看懂官方题解,我的做法是找到树的重心,然后跑一遍dfs即可。复杂度应该是O(2n),可能vector被卡常了?,以后还是记得开氧气优化。
#pragma GCC optimize(2)
#include
using namespace std;
typedef long long ll;
const int maxn=1e6+10;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
ll read(){
ll f=1,x=0;char ch;
do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
return f*x;
}
int n,ans,size=INF;
vector<int>G[maxn];
int son[maxn],vis[maxn];
void dfs(int cur){
vis[cur]=1;
son[cur]=0;
int tmp=0;
for(int i=0;i<G[cur].size();i++){
int u=G[cur][i];
if(!vis[u]){
dfs(u);
son[cur]+=son[u]+1;
tmp=max(tmp,son[u]+1);
}
}
tmp=max(tmp,n-son[cur]-1);
if(tmp<size || tmp==size && cur<ans){
ans=cur;
size=tmp;
}
}
ll sum=0;
void dfs2(int x,int fa,int dep){
for(int i=0;i<G[x].size();i++){
int u=G[x][i];
if(u==fa)continue;
dfs2(u,x,dep+1);
}
sum=sum+1ll*dep;
}
int main(){
scanf("%d",&n);
for(int i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
dfs(1);
dfs2(ans,-1,0);
printf("%lld\n",sum);
return 0;
}
题意:对于每个点i有pi的概率往右走,问走完n个点的期望是多少。
题解:概率dp的题目。设 d i d_i di为在当前第i个任务到结束还有多久,那么对于第i个点它有 p i p_i pi的概率跳到后面一天还有 1 − p i 1-p_i 1−pi的概率回到前面一天,所以对应的方程就为 − ( 1 − p i ) d i − 1 + d i − p i d i + 1 = 1 -(1-p_i)d_{i-1}+d_i-p_id_{i+1}=1 −(1−pi)di−1+di−pidi+1=1,那么列出所有的方程组,高斯消元即可解决,btw如果直接用高斯消元会有精度问题最后只能85,但如果我们直接拿On扫一遍的话就可以过了。。
#include
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
ll read(){
ll f=1,x=0;char ch;
do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
return f*x;
}
int n;
double a[maxn],f[maxn][5],d[maxn];
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%lf",&a[i]);
for(int i=1;i<=n;i++)
d[i+1]=(d[i]-1+(a[i]-1)*d[i-1])/a[i];
printf("%.3lf\n",-d[n+1]);
return 0;
}