A Car Show
题意
NIO王国有n城和m车系。根据调查,在第i个城市,Ti风格的汽车是最受欢迎的。现在NIO王国要举办车展,负责人想选择一个整数区间[l,r](1≤l≤r≤n)让指数在这个区间的城市联合举办车展。为了体现汽车的多样性,每种款式都应该在主办城市最受欢迎的款式中至少出现一次。确定满足上述约束的整数区间数。即给定一个长为n的包含1,2,...,m的序列,求有多少区间[L,R]包含所有1,2,...,m。
思路
最开始将左端点设为1,在输入t[i]的同时,统计数字t[i]的个数,和不同的数字一共出现多少个(不需要考虑顺序和大小,直接判断新输入的数字的原个数是否为0,若为0则此是新数字,种类数加一),当种类数等于m时表明在此时的左右端点之间,所有种类的数字都至少出现过一次,在左端点不变的情况下,右端点可选择此时输入位置到末尾的任一位置,随后考虑此时位置不变时,向右移动左端点是否满足所有种类数字都至少出现过一次,当使左端点数字的个数减一(表示左端点右移)时,如果该数字的个数仍大于0,则依然满足;否则继续输入新数字。
代码
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <deque>
#include <stdio.h>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <iomanip>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define int long long
#define pii pair<int,int>
using namespace std;
int t[100005];
int shu[100005];
signed main()
{
IOS;
int n,m;
cin>>n>>m;
int you;
int ji=0;
int sum=0;
int zuo=1;
for(you=1;you<=n;you++)
{
cin>>t[you];
if(shu[t[you]]==0)
{
ji++;
}
shu[t[you]]++;
while(ji==m)
{
sum+=n-you+1;
shu[t[zuo]]--;
if(shu[t[zuo]]==0)
ji--;
zuo++;
}
}
cout<<sum<<endl;
return 0;
}
B Two Frogs
题意
河道里有n个荷叶排成一排,从第i(<n)个荷叶出发可以跳到第(i,i+ai]个荷叶上,有两只青蛙从第1个荷叶出发,每一步都独立地等概率随机地跳向后边的荷叶,求两只青蛙以相同步数到达第n个荷叶的概率。
思路
采用dp[i][j]来表示采用i步到达j的概率。因为要求两只青蛙相同步数到达第n个荷叶的概率,所以结果应为dp[i][n]的平方和。在计算之前,应先求出a[i]的逆元,即(1/a[i]),表示在i荷叶上选择跳几步的概率。在计算过程中,青蛙在荷叶i上跳跃,可以选择(i,i+a[i]]步,即dp[j][i+k]=(dp[j][i+k]+dp[j-1][i]*inv[i]%mod)%mod,意为第j次跳跃,从第i个荷叶上跳跃,选择一次跳k步,跳到i+k荷叶上的概率是上一次跳跃即第j-1次跳到第i个荷叶上此时从第i个荷叶上选择一个合理数值进行跳跃,概率即为之前跳到i的概率乘以数值选择概率。但是如果一个数一个数的计算,结果会超时,所以应采用差分的思想来计算。
代码
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <deque>
#include <stdio.h>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <iomanip>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define int long long
#define pii pair<int,int>
using namespace std;
int a[8005];
int dp[8005][8005];//i步到j 的概率
int mod=998244353;
int c[8005],inv[8005];
int qiu(int a,int b)
{
int temp=1;
while(b)
{
if(b&1)
temp=temp*a%mod;
a=a*a%mod;
b>>=1;
}
return temp;
}
signed main()
{
IOS;
int n;
cin>>n;
int i,j;
int sum;
for(i=1;i<n;i++)
{
cin>>a[i];
}
for(i=1;i<n;i++)//求i的逆元
inv[i]=qiu(a[i],mod-2);
dp[0][1]=1;
for(i=1;i<n;i++)
{
for(j=i;j<n;j++)
{
c[j+1]=(c[j+1]+dp[i-1][j]*inv[j])%mod;
c[j+a[j]+1]=(c[j+a[j]+1]-dp[i-1][j]*inv[j]%mod+mod)%mod;
}
sum=0;
for(j=1;j<=n;j++)
{
sum=(sum+c[j])%mod;
c[j]=0;
dp[i][j]=sum;
}
}
int cnt=0;
for(i=1;i<n;i++)
{
cnt=(cnt+dp[i][n]*dp[i][n]%mod)%mod;
}
cout<<cnt<<endl;
return 0;
}