题意:
给出n个球,每个球上都有一个数字。
可以使用魔法:取出任意两个球,其上数字分别为s,p,
往里面放入一个新的球,它的值为s+p+s*p。
问,最后剩下一个球,这个球的期望值是多少?
思路:
简单模拟一下可知取球的顺序不会影响最后的结果。
因此直接两两挨着操作即可。
代码:
#include
using namespace std;
typedef long long ll;
typedef long double ld;
const int mod = 998244353,N = 1000;
ll a[N];
int main(){
int t,n;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=1;i<=n;i++) {
scanf("%d",&a[i]);
}
ll x=a[1];
for(int i=2;i<=n;i++){
x=((x+a[i])%mod+x*a[i]%mod)%mod;
}
printf("%lld\n",x);
}
return 0;
}
题意:
俄罗斯套娃。
最初给出n个洋娃娃的大小ai,初始就是按升序给出的。
把n个洋娃娃分成k组,使得每组内的相邻两个洋娃娃的ai
的差值>=r。问一共有多少种方案数?
思路:
首先考虑是一个将n个物品分成m组的问题,是一个划分数问题,模板为:
#include
#include
using namespace std;
int dp[1001][1001];
int main()
{
int n, m;
cin >> n >> m;
dp[0][0] = 1; //把0个人分为0份方案为1
dp[0][1] = 0; //把0个人分为1份方案为0
for(int i=1;i<=n;i++)
for (int j = 1;j <= m;j++)
{
dp[i][j] = dp[i - 1][j - 1]; //有1的情况
if (i >= j)
{
dp[i][j] += dp[i - j][j]; //无1的情况
}
}
cout << dp[n][m];
}
因为这个题它有特殊的限制条件:后面的娃要能够套在前面的娃上,那么套上的相邻两个娃的大小差值要>=r。设dp[i][j]表示前i个娃分成j组的方案数,那么考虑第i个娃时, 代码:
(1)可以单独分成一组,此时dp[i][j]=dp[i-1][j-1];
(2)也可以套在以前的娃上,那么组数不变,由dp[i-1][j]转移而来,那么之前有多少个可以套的娃呢?
先统计a[i]-a[j]
#include
题意:
给出一个n个点的带权图,从i到j的边权为gcd(i,j)。
给出q次询问,每次询问输出点u和点v之间的最短距离以及路径条数。
思路:
最短路的长度一定<=2。
当gcd(u,v)==1时,最短路长度为1且只有一条;
否则,最短路长度为2,当gcd(u,v)==2时,
ans+=1;ans+= gcd(u,p)==1&&gcd(p,v)==1的点p的数量,
分解u,v后用容斥可以计算。
代码:
#include
using namespace std;
typedef long long ll;
const int N = 1e7+10,mod= 998244353;
int prime[N/10],f[N],n,m,q,res;//f[i]表示i的最小质因子
set st;
vector a;
bool p[N];
int gcd(int a,int b){
return b?gcd(b,a%b):a;
}
void Prime(int n){
int cnt=0;
for(int i=2;i<=n;i++){
//p数组标记这个数是否为质数
//如果i就是质数,那么最小质因子就是它本身
if(!p[i]) prime[++cnt]=i,f[i]=i;//prime数组记录所有质数
for(int j=1;j<=cnt&&prime[j]*i<=n;j++){
p[prime[j]*i]=1;
f[prime[j]*i]=prime[j];//最小质因子是prime[j]
if(i%prime[j]==0) break;
}
}
}
void div(int x){
while(x>1){
int y=f[x];//获取x的最小质因子
if(!st.count(y)) st.insert(y);
while(x%y==0) x/=y;//除尽这个质因子
}
}
void dfs(int x,int y,int z){
if(x==m){
res+=z*(n/y)%mod;
return;
}
dfs(x+1,y,z);
if(y<=n/a[x]) dfs(x+1,y*a[x],-z);//容斥
}
int work(int x,int y){
st.clear();
a.clear();
div(x),div(y);
for(auto it:st) a.push_back(it);//将set里面的所有元素放进vector数组中
m=a.size();
res=0;
dfs(0,1,1);
return res;
}
int main(){
scanf("%d%d",&n,&q);
Prime(n);
while(q--){
int u,v;
scanf("%d%d",&u,&v);
if(gcd(u,v)==1){
puts("1 1");
}
else{
int ans=work(u,v);
if(gcd(u,v)==2) ans++;
ans%mod;
printf("2 %d\n",ans);
}
}
return 0;
}