zoukankan      html  css  js  c++  java
  • 题解 分手是祝愿

    whca!!!

    题目传送门

    Description

    (n) 盏初始状态为 (a_{1,2,...,n}) 的灯,在修改一个灯的状态时它的所有因子都会跟着修改,每次随机修改一个点的状态,在把剩余灯都关掉的最小操作次数 (le k) 的时候会直接采用最优方案。问期望操作次数乘上 (n!)

    (nle 10^5)

    Solution

    可以(bu neng) 想到的是,一个灯的影响不能通过其它灯组合(不包含该灯)来实现,也就是说一定是有些灯是必须要按的(或者说叫按奇数次),我们设有 (s) 个这种灯,而其它的灯按了之后必须按回来。

    那我们就可以设计状态 (f_i) 表示现在有 (i) 盏需要按的灯,把需要按的灯的数量从 (i) 变为 (i-1) 的期望操作次数。可以得到转移式:

    [f_i=frac{i}{n}+frac{n-i}{n} imes (f_{i+1}+f_i+1) ]

    (frac{i}{n}) 表示直接按到需要按的灯上去了,(frac{n-i}{n}) 意义则相反,(f_{i+1}+f_{i}+1) 表示你按错了一个灯,你就需要按回来,你还要按到 (i-1),还要加上你按错的这一次。

    移项之后就可以得到:

    [f_i=frac{n+(n-i) imes f_{i+1}}{i} ]

    边界条件就是 (f_{n+1}=0),显然你不能拿 (f_{s+1}) 作为边界条件,因为你按错了就会变成 (s+1)

    答案就是 ((sum_{i=k+1}^{s} f_i+k) imes n!)。当 (sle k) 的时候直接输出 (s) 即可。

    Code

    #include <bits/stdc++.h>
    using namespace std;
    
    #define Int register int
    #define MAXN 100005
    #define mod 100003
    
    template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
    template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
    template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
    
    int n,k,cnt,a[MAXN],f[MAXN];
    
    int mul (int a,int b){return 1ll * a * b % mod;}
    int dec (int a,int b){return a >= b ? a - b : a + mod - b;}
    int add (int a,int b){return a + b >= mod ? a + b - mod : a + b;}
    int qkpow (int a,int b){
    	int res = 1;for (;b;b >>= 1,a = mul (a,a)) if (b & 1) res = mul (res,a);
    	return res;
    }
    void Add (int &x,int y){x = add (x,y);}
    
    void makeit (int x){
    	for (Int i = 1;i * i <= x;++ i) if (x % i == 0){
    		a[i] ^= 1;
    		if (i * i != x) a[x / i] ^= 1;
    	}
    }
    
    signed main(){
    	read (n,k);
    	for (Int i = 1;i <= n;++ i) read (a[i]);
    	for (Int i = n;i >= 1;-- i) if (a[i]) makeit (i),++ cnt;
    	for (Int i = n;i >= k;-- i) f[i] = mul (add (n,mul (n - i,f[i + 1])),qkpow (i,mod - 2));
    	int ans = 0;
    	if (cnt > k){
    		for (Int i = cnt;i > k;-- i) Add (ans,f[i]);
    		Add (ans,k);
    	}
    	else ans = cnt;
    	for (Int i = 1;i <= n;++ i) ans = mul (ans,i);
    	write (ans),putchar ('
    ');
    	return 0;
    }
    
  • 相关阅读:
    2021.4.14
    每日总结
    每日总结
    每日总结
    oracle db组面试 复习数据库
    二叉树根结点到叶节点的最短距离
    minheap 最小堆的实现
    Maximum element in a sorted and rotated array排序和旋转数组中的最大元素
    树和图bfs的一个共同点
    117. Populating Next Right Pointers in Each Node II 不完全二叉树连接右边节点
  • 原文地址:https://www.cnblogs.com/Dark-Romance/p/14791754.html
Copyright © 2011-2022 走看看