E - Justifying the Conjecture
题意:
给定 n n n,问 n n n是否能由一个素数 x x x和一个非素数 y y y相加得到?
做法:
思维题,当
n
<
=
5
n<=5
n<=5时,首先素数有2,3,5,非素数有1,4;根本无法构成题目要求所以直接输出
−
1
-1
−1 ,接下来就是大于5的情况了,首先如果是个偶数,那么他必然可以分成
2
+
n
−
2
2+n-2
2+n−2,所有的偶数都是
2的倍数,所以后一个数一定不是素数,其次就是奇数,保守估计了一下直接拆成
3
+
n
−
3
3+n-3
3+n−3
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const ll N=1e8+5;
//int prime[N];
//bool visit[N];
/*void Prime()
{
int cnt=0;
memset(visit,false,sizeof(visit));
for (int i = 2; i <= N; i++)
{
if (!visit[i])
{
prime[++cnt] = i;
}
for (int j = 1; j <=cnt; j++)
{
if(i*prime[j]>maxn)
break;
visit[i*prime[j]]=true;
if(i%prime[j]==0)
break;
}
}
}*/
int main()
{
int T,n;
//Prime();
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
if(n<=5)
cout<<-1<<endl;
else
{
if(n&1)
cout<<3<<" "<<n-3<<endl;
else
cout<<2<<" "<<n-2<<endl;
}
}
return 0;
}
F - Keeping Rabbits
题意:
初始给出 n n n个重量,假设总和为 s u m sum sum,每个兔子每天的体重增加1的概率是他占所有的兔子的总的重量的比例。问 k k k天之后每只兔子的重量的期望值是多少?
做法:
数学期望计算,我们知道k天之后所有的兔子的总的重量增加为k,那么我们现在就是要把这
k
k
k分配到
n
n
n只兔子上面。根据题目给定公式
然后进一步推出
a
[
i
]
=
a
[
i
]
+
k
∗
(
a
[
i
]
∗
k
/
s
u
m
)
a[i]=a[i]+k∗(a[i]∗ k/sum)
a[i]=a[i]+k∗(a[i]∗k/sum)。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
ll a[maxn],s;
int main()
{
ios::sync_with_stdio(false);
int T,n,k;
scanf("%d",&T);
while(T--)
{
s=0;
scanf("%d%d",&n,&k);
for(int i=1; i<=n; i++)
scanf("%lld",&a[i]),s+=a[i];
for(int i=1; i<=n; i++)
{
printf("%.8lf",a[i]+a[i]*k*1.0/s);
if(i!=n)
printf(" ");
}
printf("\n");
}
return 0;
}
B - Fixing Banners
题意:
从6个字符串里面各取一个字符,问是否可以可以拼接成一个字符串 ′ h a r b i n ′ 'harbin' ′harbin′。
做法:
暴力美学,直接用map去存每一个字符且标出位置,然后dfs跑每一个给定的字符,最后判断一下输出。也可以预处理然后全排列。全排列的话这位dalao讲得好传送门
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
map<char,int> mp;
bool pos[10][10],vis[10];
int ans;
string s[10];
void init()
{
memset(pos,false,sizeof(pos));
for(int i=0;i<6;i++)
{
for(int j=0;j<s[i].size();j++)
{
if(mp.count(s[i][j])==0)
continue;
else
pos[i][mp[s[i][j]]]=true;
}
}
memset(vis,false,sizeof(vis));
}
void dfs(int x)
{
if(x==6||ans==1)
{
ans=1;
return;
}
for(int i=0;i<6;i++)
{
if(vis[i]||!pos[i][x+1])
continue;
else
{
vis[i]=true;
dfs(x+1);
vis[i]=false;
}
}
}
int main()
{
ios::sync_with_stdio(false);
int T,n,k;
mp.clear();
mp['h']=1,mp['a']=2,mp['r']=3,mp['b']=4,mp['i']=5,mp['n']=6;
cin>>T;
while(T--)
{
ans=0;
for(int i=0;i<6;i++)
cin>>s[i];
init();
dfs(0);
if(ans)
cout<<"Yes"<<endl;
else
cout<<"No"<<endl;
}
return 0;
}
D - Interesting Permutation
题意:
现在你手上有四个数组 a , f , g , h a,f,g,h a,f,g,h,但是你只确定一个数组h里的元素。巧的是你还知道
- 对于每一个 1 < = i < = n 1<=i<=n 1<=i<=n,都有 f [ i ] = m a x ( a 1 , a 2..... , a i ) f[i]=max(a1,a2.....,ai) f[i]=max(a1,a2.....,ai)
- 对于每一个 1 < = i < = n 1<=i<=n 1<=i<=n,都有 g [ i ] = m i n ( a 1 , a 2..... , a i ) g[i]=min(a1,a2.....,ai) g[i]=min(a1,a2.....,ai)
- 对于每一个 1 < = i < = n 1<=i<=n 1<=i<=n,都有 h [ i ] = f [ i ] − g [ i ] h[i]=f[i]-g[i] h[i]=f[i]−g[i]
问你是否可以通过 h h h数组推出原来 a a a数组有多少种合法排列呢?最后的答案需要对 1 e 9 + 7 1e9+7 1e9+7取模
做法:
啥叫a的合法排列呢?就是你求出的a数组要能够再次构成h数组。其实没啥用OMO
首先咱来分析一下
h
的
合
法
性
h的合法性
h的合法性
- h h h数组第一个数字必然是 0 0 0,因为 a [ 1 ] a[1] a[1]只有一个元素,最大最小都是自己,所以 h [ 1 ] = 0 h[1]=0 h[1]=0
- h h h数组最后一个数字必然是 n − 1 n-1 n−1,类似于上边,整个 a a a数组最大值是 n n n,最小值是 1 1 1,所以 h [ n ] = n − 1 h[n]=n-1 h[n]=n−1
-
h
h
h数组必定
单
调
不
递
减
单调不递减
单调不递减,因为都是最大值减最小值,所以越往后h的值必定
越
来
越
大
越来越大
越来越大,不可能会变小
确定了h的合法性,再观察观察h的构成 h [ i ] = f [ i ] − g [ i ] = > h [ i ] = m a x ( a 1 , a 2..... , a i ) − m i n ( a 1 , a 2..... , a i ) h[i]=f[i]-g[i]=>h[i]=max(a1,a2.....,ai)-min(a1,a2.....,ai) h[i]=f[i]−g[i]=>h[i]=max(a1,a2.....,ai)−min(a1,a2.....,ai)。所以当 h [ i ] ! = h [ i − 1 ] h[i]!=h[i-1] h[i]!=h[i−1]时必然是最值有改变(可能是最大值变了也可能是最小值变了)所以这里是两种情况;接下来 h [ i ] > h [ i − 1 ] h[i]>h[i-1] h[i]>h[i−1]中间会有一个数字区间空出来,而我们需要做的只需要从这些数字中抽出来一个就能构成 a a a数组中的对应元素啦
整理一下
两个条件 - h [ i ] = = h [ i − 1 ] , a n s = a n s ∗ c n t , c n t − − h[i]==h[i-1],ans=ans*cnt,cnt-- h[i]==h[i−1],ans=ans∗cnt,cnt−−
-
h
[
i
]
>
h
[
i
−
1
]
,
a
n
s
=
a
n
s
∗
2
,
c
n
t
+
=
(
h
[
i
]
−
h
[
i
−
1
]
−
1
)
h[i]>h[i-1],ans=ans*2,cnt+=(h[i]-h[i-1]-1)
h[i]>h[i−1],ans=ans∗2,cnt+=(h[i]−h[i−1]−1)
最后不要忘记了取模呀!
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const int mod=1e9+7;
int n,m,q;
ll h[maxn];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int flag=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%lld",&h[i]);
if(h[1]!=0||h[n]!=n-1)
{
printf("0\n");
continue;
}
ll ans=1,cnt=0,maxx=0;
for(int i=2;i<=n;i++)
{
maxx=max(h[i],maxx);
if(h[i]<maxx)
{
flag=1;
break;
}
if(h[i]>h[i-1])
{
ans=ans*2%mod;
cnt+=(h[i]-h[i-1]-1);
}
else if(h[i]==h[i-1])
{
ans=ans*cnt%mod;
cnt--;
}
}
if(flag)
printf("0\n");
else
printf("%d\n",(ans+mod)%mod);
}
return 0;
}
每日小结:
终于呀!不欠账了呀!nice!一周结!周赛前疯狂补题,(╥╯^╰╥)最近又开始瞎浪了,今天好说好歹是给自己整起来了,没有咸鱼的一天!充实的一匹!最近的Linux学的有点舒服,主要是上学期的忘的差不多了,啥也不会了QAQ还是一条老咸鱼呀,7天我们也要打这半年来的最后一场了,加油!愿明天的朝阳能给予我开心过完一天的好运呀!Thanks♪(・ω・)ノ