[六省联考2017]分手是祝愿(期望+DP)

题解

很容易想出来最优策略是什么。

就是从n到1看到开着的灯就把它关了

我们预处理出当前状态把灯全部关闭后的最少步数cnt

然后我们的主人公就要瞎按。。。

设dp[i]代表当前状态最优解为i步时走到dp[i-1]用过步数的期望。

现在我们考虑如何转移到dp[i]

当我们这一步走到当前最优策略的一步时。

dp[i]=i/n*1

当我们这一步没有走到当前最优策略的一步时。

dp[i]=(n-i)/n*(dp[i+1]+1+dp[i])

所以 dp[i]=i/n+(n-i)/n*(dp[i+1]+1+dp[i])

化简一下 dp[i]=(n+(n-i)*dp[i+1])/i;

这样求出dp后答案就是dp[1]+dp[2]+...+dp[cnt]

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<vector>
 7 using namespace std;
 8 const long long N=1000100;
 9 const long long mod=100003;
10 vector<long long>vec[N];
11 long long n,k,inv[N],a[N],cnt,dp[N],ans;
12 long long read(){
13     long long sum=0,f=1;
14     char ch=getchar();
15     while(ch<'0'||ch>'9'){
16         if(f=='-')f=-1;
17         ch=getchar();
18     }
19     while(ch<='9'&&ch>='0'){
20         sum=(sum<<1)+(sum<<3)+ch-'0';
21         ch=getchar();
22     }
23     return sum;
24 }
25 int main(){
26     n=read();k=read();
27 //    scanf("%d%d",&n,&k); 
28     inv[1]=1;
29     for(long long i=2;i<=n;i++){
30         inv[i]=-(mod/i)*inv[mod%i];
31         inv[i]=(inv[i]%mod+mod)%mod;
32     }
33     for(long long i=1;i<=n;i++)
34         for(long long j=i;j<=n;j+=i){
35             vec[j].push_back(i);
36         }
37     for(long long i=1;i<=n;i++){
38     //    scanf("%d",&a[i]);
39         a[i]=read();
40     }
41     for(long long i=n;i>=1;i--){
42         if(a[i]){
43             for(long long j=0;j<=vec[i].size()-1;j++){
44                 a[vec[i][j]]^=1;
45             }
46             cnt++;
47         }
48     }
49     dp[n]=1;
50     for(long long i=n-1;i>k;i--){
51         dp[i]=(n+(n-i)*dp[i+1])%mod*inv[i]%mod;
52     }
53     for(long long i=k;i>=1;i--)dp[i]=1;
54     for(long long i=1;i<=cnt;i++){
55         ans+=dp[i];
56         ans%=mod;
57     }
58     for(long long i=1;i<=n;i++){
59         ans*=i;
60         ans%=mod;
61     }
62     printf("%lld",ans);
63     return 0;
64 } 

 

posted @ 2018-09-09 17:06  Xu-daxia  阅读(253)  评论(0编辑  收藏  举报