I Chiitoitsu
题意
最开始有13张牌,相同的牌最多出现两张。每次摸一张牌,如果实现有七对相同的牌即结束;否则从自己的牌中选一张丢掉。求在最优策略下,结束的预期回合数。
思路
因为最开始相同的牌最多出现两张,所以最优策略是如果后摸到的牌可以与现有的牌构成一对就留下,丢弃现有牌中无法与其他牌构成一对的牌;如果后摸到的牌不能与现有的牌构成一对,就将它丢掉。
求期望dp,令 f(s,r) 表示当前手牌中有 s 张单牌且牌堆中剩余 r 张牌时构成七对牌的期望轮数,则有: 当s=1时,f(s,r)=1+(r-3)/r*f(1,r-1);当s>1时,f(s,r)=1+3*s/r*f(s-2,r-1)+(r-3*s)/r*f(s,r-1)。
对于给定的初始手牌,设其单牌数量为 s0,则 f(s0,136−13) 即为答案。
代码
#include <iostream>
#include <cstring>
#include <cmath>
#include <map>
#define int long long
using namespace std;
char s[200005];
int dp[20][200];
map<string,int> mp;
int inf=1e9+7;
int pow(int x,int n){
int res=1;
while(n){
if(n%2)
res=x*res%inf;
x=x*x%inf;
n/=2;
}
return res;
}
void init(){
for(int i=1;i<=13;i+=2)
for(int j=1;j<=123;j++){
if(i==1)
dp[i][j]=(1+((j-3)*pow(j,inf-2)%inf)*dp[i][j-1])%inf;
else
dp[i][j]=(1+(i*3*pow(j,inf-2)%inf)*dp[i-2][j-1]%inf+((j-3*i)*pow(j,inf-2)%inf)*dp[i][j-1]%inf)%inf;
}
}
signed main(){
ios::sync_with_stdio(false);
int t;
cin>>t;
init();
int i,j,k;
int op=0;
string s1;
while(t--){
op++;
cin>>s+1;
cout<<"Case #"<<op<<": ";
mp.clear();
for(i=2;i<=26;i+=2){
s1="";
s1+=s[i-1];
s1+=s[i];
mp[s1]++;
}
int cnt=0;
for(auto u:mp){
if(u.second==1)
cnt++;
}
cout<<dp[cnt][123]<<endl;
}
}
A Villages: Landlines
题意
数轴上有一个发电站与n−1个建筑物,发电站和建筑物必须通过电力塔连接,如果电力塔与发电站的距离小于发电站的半径范围,则不需要电线;如果电力塔与建筑物的距离小于建筑物半径,则不需要电线;如果电力塔与它们的距离大于它们相应的半径就需要距离差的电线。
思路
个人感觉这个题目较难理解,但通过示例画图可以更好地理解
本题是区间合并问题,先算出发电站和建筑物各自的范围,通过sort排序,使区间整体从左到右排好,再进行遍历,寻找没有区间覆盖的地方。
代码
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
struct node
{
int x;
int r;
int l;
int you;
}pos[200005];
bool cmp(node a,node b)
{
if(a.l!=b.l)
return a.l<b.l;
return a.you<b.you;
}
int main()
{
int n;
cin>>n;
cin>>pos[0].x>>pos[0].r;
pos[0].l=pos[0].x-pos[0].r;
pos[0].you=pos[0].x+pos[0].r;
int i,j;
for(i=1;i<n;i++)
{
cin>>pos[i].x>>pos[i].r;
pos[i].l=pos[i].x-pos[i].r;
pos[i].you=pos[i].x+pos[i].r;
}
sort(pos,pos+n,cmp);
long long sum=0;
int biaol=pos[0].l;
int biaor=pos[0].you;
for(i=1;i<n;i++)
{
if(pos[i].l>biaor)
{
//cout<<biaor<<" "<<pos[i].l<<" "<<i<<endl;
sum+=pos[i].l-biaor;
biaor=pos[i].you;
}
else
{
biaor=max(pos[i].you,biaor);
//cout<<pos[i].you<<" "<<biaor<<endl;
}
}
cout<<sum;
return 0;
}
D Lexicographical Maximum
题意
给定n,将 1, 2, . . . , n 视为不含前导零的字符串 求这些字符串中字典序最大的字符串
思路
答案除去最后一位,其余位均为 9 。如果n除去最后一位,其余为均为 9 ,则答案即为 n ;若不然则答案为 |n| − 1 个 9
代码
#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
int main()
{
string s;
cin>>s;
int i,j;
int op=-1;
for(i=0;s[i+1]!=0;i++)
{
if(s[i]!='9')
op=i;
cout<<"9";
}
if(op==-1)
cout<<s[i];
return 0;
}