很多的东西用法不知道
像2维字符串怎么输入
后来知道了:
字符串数组(2维字符数组)不能直接输入
(最好增加一个字符串,每次输入这个,再把它存到字符串数组中去,也可以char s[][];scanf("%s",%s[i]))
字符串不能初始化0,新定义的字符串原本就是空的(像s=0)
题1:number
题⽬描述给定⼀个1~n的排列,每⼀次可以对该排列进⾏这样的操作:
从排列中任意拿出⼀个数,放在该序列的最前⾯。
问⾄少经过多少次操作,可以使该排列变为1, 2, 3......n-1, n。
输⼊格式
输⼊包含多组数据。
第⼀⾏⼀个整数T( T<=10),表⽰数据组数。
对于每组数据,第⼀⾏⼀个整数n表⽰排列的长度,接下来⼀⾏n个数表⽰
这个排列。
输出格式
对于每组数据,输出⼀个整数,表⽰最少经过⼏次操作可以恢复正常顺序。
样例输⼊
2
4
4 1 2 3
5
1 2 3 4 5
样例输出
3
0
样例说明
对于50%的数据
对于第⼀组数据,操作顺序为:
(4,1,2,3) → (3,4,1,2) → (2,3,4,1) → (1,2,3,4)。
对于第⼆组数据,已经是正常的顺序所以不需要任何操作了。
数据范围
对于50%的数据 n ≤ 10。
对于80%的数据 n ≤ 1000。
对于100%的数据 n ≤ 100000。
。。。
题目一定要看仔细
结论不要片面
从大往小的位置检查
因为从大的开始确定
只要保持大的几个连续的确定就行了
(而我片面的认为一定要在最前面)
代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
freopen("seq.in","r",stdin);
freopen("seq.out","w",stdout);
int n;
cin>>n;
int a[2010]={};
double F[5010]={},f[5010]={};
for(int i=1;i<=n;i++)
cin>>a[i];
sort(a+1,a+1+n);
double g=n*(n-1)/2;
for(int i=1;i<n;i++)
for(int o=i+1;o<=n;o++)
f[a[o]-a[i]]+=double(1)/g;
int mx=a[n]-a[1];
for(int i=1;i<=mx;i++)
for(int o=1;o<=mx;o++)
F[i+o]+=f[i]*f[o];
for(int i=1;i<=mx;i++)
F[i]+=F[i-1];
double ans=0;
for(int i=1;i<=mx;i++)
ans+=F[i-1]*f[i];
printf("%.4lf",ans);
fclose(stdin);
fclose(stdout);
return 0;
}
题2:sort
题⽬描述
给定 n 个由⼩写字母组成的字符串,请你求出⼀个字母表顺序,使得这 n
个字符串是按照字典序升序排列的,数据保证存在合法的字母表顺序。
多个解按字典需最大
输⼊格式
第⼀⾏⼀个整数 n。
接下来 n ⾏,每⾏⼀个字符串。
输出格式
⼀⾏,⼀个 a ∼ z 各出现⼀次的字符串,表⽰字母表顺序 。
样例输⼊
10
petr
egor
endagorion
feferivan
ilovetanyaromanova
kostka
dmitriyh
maratsnowbear
bredorjaguarturnik
cgyforever
样例输出
aghjlnopefikdmbcqrstuvwxyz
数据范围
对于30%的数据 n<=100。
对于100%的数据 n<=1000,字符串长度<=1000。
我之前太钻牛角尖了
非要递归求不同的
用spfa求还要用万能节点
同时题意理解有些偏差
以为如果确定的不满26个字符还要
按字典序吧没有的补上去
好的解法是拓扑排序
代码:
#include<bits/stdc++.h>
using namespace std;
const int dd=100010;
int e[dd],next[dd],link[dd],top=0;
char str[dd];
int cs[200]={};
inline void into(int xx,int yy){e[++top]=yy,next[top]=link[xx],link[xx]=top;}
int main()
{
int n;
cin>>n;
string s[1010];
for(int i=1;i<=n;i++)
scanf("%s",&s[i]);
for(int i=1;i<n;i++)
{
int pd=0;
int l=min(s[i].size(),s[i+1].size());
for(int o=0;o<l;o++)
{
if(s[i][o]!=s[i+1][o])
{
pd=1;
into(s[i][o],s[i+1][o]);
cs[s[i+1][o]]++;
break;
}
}
if(!pd&&s[i].size()>s[i+1].size())
{
cout<<"Impossible";
return 0;
}
}
queue<int>q;
for(int i='a';i<='z';i++)
if(!cs[i])
q.push(i);
string ans;
while(!q.empty())
{
int u=q.front();
q.pop();
ans+=(char)u;
for(int i=link[u];i;i=next[i])
{
if(!--cs[e[i]])
{
q.push(e[i]);
}
}
}
if(ans.size()!=26) cout<<"Impossible";
else cout<<ans;
return 0;
}
题3:seq
题⽬描述给定⼀个长度为n的序列, A与B 随机从序列中拿⼀个数(放回)谁的⼤算
谁赢,⽐赛三局两胜,已知A与B的⽐赛结果为前两局A胜,第三局B胜。求这
三局B取得数的和⽐A取得数的和⼤的概率。
输⼊格式
第⼀⾏⼀个整数n,⼀⾏n个正整数表⽰序列中的每⼀个数ai。
输出格式
输出⼀个实数,保留四位⼩数。
样例输⼊
3
1 2 10
样例输出
0.0741
数据范围
对于20%的数据 n<=20。
对于40%的数据 n<=200。
对于100%的数据 n<=2000, 1<=ai<=5000。
这题正解跟dp较像
先求出相差x的概率f[]
求出A前两次大B的概率F[i+o]=f[i]*f[o]
求出A前两次大B的前缀和F[x]+=F[x-1]
枚举f
计算f[]>F[]的所有
就相当ans+=f[i]*f[i-1]
代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
freopen("seq.in","r",stdin);
freopen("seq.out","w",stdout);
int n;
cin>>n;
int a[2010]={};
double F[5010]={},f[5010]={};
for(int i=1;i<=n;i++)
cin>>a[i];
sort(a+1,a+1+n);
double g=n*(n-1)/2;
for(int i=1;i<n;i++)
for(int o=i+1;o<=n;o++)
f[a[o]-a[i]]+=double(1)/g;
int mx=a[n]-a[1];
for(int i=1;i<=mx;i++)
for(int o=1;o<=mx;o++)
F[i+o]+=f[i]*f[o];
for(int i=1;i<=mx;i++)
F[i]+=F[i-1];
double ans=0;
for(int i=1;i<=mx;i++)
ans+=F[i-1]*f[i];
printf("%.4lf",ans);
fclose(stdin);
fclose(stdout);
return 0;
}