Educational Codeforces Round 47 (Rated for Div. 2) D.(暴力+gcd)or(欧拉函数) E. (概率+逆元)

D题链接:http://codeforces.com/contest/1009/problem/D

题意,给你n、m两个数,n为图的点数,m为图的边数,G=(V,E)让你求满足下列条件的图G:①(u,v)€E   ②gcd(u,v)=1;如果u和v之间没有边则gcd(u,v)是无关系的;

  如果不能构成这样的图输出“Impossible”

  如果能构成这样的图输出“Possible”;并输出图的边。

  (1<=n,m<=1e5)

分析:方法一:其实我们可以直接枚举u,v两个点暴力求取gcd(u,v);看似是O(n^2logn)的复杂度,但实际情况却不是这样的,因为1是与2~n的数互质的,这样我们就有n-1条边了;

  方法二:预处理欧拉函数(小于等于n且与n互质的数的个数);用欧拉函数还做。

  PS:在比赛的时候想的是方法一,所以第二种就没写代码(懒);

  悲剧的是忘记判断m<n-1,此时我们应该输出的是“Impossible”,因为n个点要构成图至少需要n-1条边,比赛的时候没注意这个疯狂WA 在第九组数据。orz。哎!~!

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<math.h>
 4 #include<queue>
 5 #include<vector>
 6 #include<set>
 7 #include<iostream>
 8 #include<cstring>
 9 #include<bits/stdc++.h>
10 using namespace std;
11 #define ll long long
12 #define ull unsinged long long
13 #define mems(a,b) memset(a,b,sizeof(a))
14 const int maxn=1e6+100;
15 int n,m;
16 pair<int,int>ans[maxn];
17 ll gcd(ll a,ll b){
18     if(b==0)return a;
19     return gcd(b,a%b);
20 }
21 
22 
23 int main()
24 {
25     scanf("%d%d",&n,&m);
26     if(m<n-1){
27         cout<<"Impossible"<<endl;
28         return 0;
29     }
30     int cnt=0;
31     for(int v=1;v<=n;v++){
32         if(cnt==m)break;
33         for(int u=v+1;u<=n;u++){
34             if(gcd(u,v)==1){
35                 cnt++;
36                ans[cnt].first=v;
37                ans[cnt].second=u;
38             }
39             if(cnt==m)break;
40         }
41     }
42     if(cnt==m){
43         cout<<"Possible"<<endl;
44         for(int i=1;i<=m;i++){
45             cout<<ans[i].first<<" "<<ans[i].second<<endl;
46         }
47     }
48     else {
49         cout<<"Impossible"<<endl;
50     }
51     return 0;
52 }
代码

 

E题链接:http://codeforces.com/contest/1009/problem/E

题意:起点为0终点为n,从起点到终点途中会有一些休息点,当你路过休息点之后你的旅游困难值就要从a1开始计算;例如:当n=7时,休息点为1和5那么旅游困难值为:3a1+2a2+a3+a4;当n=5时,休息点为2,则困难值为2a1+2a2+a3;

现在题目的要求是:他不知道有哪些休息点,考虑所有情况的话,可以有2^(n-1)种情况,休息点的选择概率是相同的。

现在要你求p*2^(n-1)的值为多少让它对mod=998244353去摸;p:的含义是困难值的均值。很显然p*2^(n-1)为正整数。

题解:

很容易就知道的是:P=∑(1,n) diffi求和;在乘以*2^(n-1)%mod;想得到上面的表达式就很简单。

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define LL long long
 4 const int maxn=1e6+100;
 5 const LL mod=998244353;
 6 int n;
 7 LL f[maxn];
 8 LL a[maxn];
 9 LL Q_Pow(LL a,LL n){
10     LL cnt=1;
11     while(n){
12         if(n&1)
13             cnt=cnt*a%mod;
14         a=a*a%mod;
15         n>>=1;
16     }
17     return cnt;
18 }
19 
20 int main()
21 {
22     while(scanf("%d",&n)!=EOF){
23         for(int i=1;i<=n;i++){
24             scanf("%lld",&a[i]);
25         }
26         memset(f,0,sizeof(f));
27         f[1]=a[1];
28         LL sump=f[1];
29         for(int i=2;i<=n;i++){
30             LL dif=(a[i]-a[i-1]);
31             //cout<<"a[i]-a[i-1]="<<dif<<endl;
32             LL t1=Q_Pow(2,i-1);
33             //cout<<"2^(i-1)="<<t1<<endl;
34             f[i]=(f[i-1]+dif*Q_Pow(t1,mod-2)%mod)%mod;
35             sump=(f[i]+sump)%mod;
36         }
37         //cout<<"sump="<<sump<<endl;
38         cout<<sump*Q_Pow(2,n-1)%mod<<endl;
39     }
40 
41     return 0;
42 }
代码

 

posted @ 2018-07-18 09:56  孟加拉国  阅读(226)  评论(0编辑  收藏  举报