【寒假集训系列2.13】

又要爆零了...

第一题数学题,第二题打了一个错误的表,找到了错误的规律(漏加1),第三题骗分(不过只有10分)

总分:100+0+10=110

诶怎么又是110,怕是跟police过不去了...

T1集合对

题目描述:

定义集合xor操作: A xor B=A∪B-A∩B。

问有多少对(P,Q)满足 P∈A ,Q∈B 使得 (P xor A)xor(Q xor B)=A xor B其中P ,Q都是集合。(答案对1e9+7取模。)

例如:A ={1} ,B={1,2},A xor B = {2},枚举所有情况P,Q有2种。

输入:

三个整数a,b,c。表示|A|,|B|,|A∩B|。

输出:

满足要求的集合对。(输出答案对10^9+7取模)

样例输入:

1 2 1

样例输出:

2

数据规模:

    50%:a,b,c<=10^6

100%: a,b,c<=10^18

  思路:xor是异或的意思嘛...然后这里稍微转换一下就发现答案是:

C(N,1)+C(N,2)+C(N,3)+...+C(N,N)  =   2^N     (N=|A∩B|))

  然后显然要快速幂啊...打上就好了...(把int #define成 long long了)

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define int long long
#define ll long long
const int MOD=1e9+7;
using namespace std;
inline int read(){
    int ans=0,f=1;char chr=getchar();
    while(!isdigit(chr)){if(chr=='-') f=-1;chr=getchar();}
    while(isdigit(chr)) {ans=(ans<<3)+(ans<<1)+chr-48;chr=getchar();}
    return ans*f;
}
inline void kai(){
    freopen("set.in","r",stdin);
    freopen("set.out","w",stdout);
}long long a,b,c;
int ksm(int x,int m){
    if(m==1) return x;
    if(m==0) return 1ll;
    int t=ksm(x,m>>1);t=t*t%MOD;
    if(m&1) return t*x%MOD;
    return t;
}
signed main(){
//    kai();
    a=read(),b=read(),c=read();
    int ans=ksm(2,c);
    cout<<ans; 
    return 0;
}

T2克拉克与数字

题目描述:

克拉克是一名人格分裂患者.某一天克拉克变成了一名数论研究者,在研究数字。

他想到了一个题:给定非负整数 x和正整数 k(1≤k≤2),可以做若干以下两种操作之一:

1.  x=x-k

2.  x=floor(sqrt(x))^2

现在克拉克想知道,这个整数最少经过多少次操作可以变成 0

输入:

第一行是一个正整数T,表示数据组数。每组数据只有一行两个整数x, k。

输出:

每组数据输出一行一个整数,表示最少的操作数。若不存在方案,输出-1。

样例输入:

2

2 1

3 2

样例输出:

2

-1

 

数据规模:

    30%:x≤100

50%:x≤2*10^9

100%: 1≤T≤100,0≤x≤10^18, 1≤k≤2

  那个啥,精度误差了解一下...

  当场打了一个搜索,暴力找规律,然后还真的找到了...

  然而,爆搜打错了...每个都漏了1,然后输出的答案也漏了1...

  正确思路好像是DP出小的数字答案,大的数字显然是要开方更划算的

  Tip:

    ·注意精度误差,系统自带的sqrt可能对较大的数有些误差,所以要调整一下(或者手打二分也可以),反正我搞这个搞了好久...

    ·小的数(小于5)没规律,要打表

代码如下:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<cmath>
 6 #define int long long
 7 using namespace std;
 8 inline int read(){
 9     int ans=0,f=1;char chr=getchar();
10     while(!isdigit(chr)){if(chr=='-') f=-1;chr=getchar();}
11     while(isdigit(chr)) {ans=(ans<<3)+(ans<<1)+chr-48;chr=getchar();}
12     return ans*f;
13 }
14 inline void kai(){
15     freopen("clarke.in","r",stdin);
16     freopen("clarke.out","w",stdout);
17 }
18 int T,x,y,ans;
19 int dfs2(int x){
20     if(x<0||x==1) return -1;
21     if(x==0) return 0;
22     if(x==2) return 1;
23     int p=floor(sqrt(x));p*=p;
24     if(p==x) return dfs2(x-2)+1;
25     int t1=dfs2(x-2),t2=dfs2(p);
26     if(t1==-1) return t2+1;
27     return min(t1,t2)+1;
28 }
29 inline int Sqrt(int n){
30     int x=sqrt(n);
31     if (x*x==n)return x;
32     if (x*x>n){while(x*x>n)x--;return x;}
33     else{while((x+1)*(x+1)<n)x++;return x;}
34 }
35 signed main(){
36     kai();
37     T=read();
38     while(T--){
39         x=read(),y=read();
40         if(y==1){
41             if(x==0) {puts("0");continue;}
42             int k=Sqrt(x);k*=k;
43             if(k==x)
44                 ans=2*Sqrt(x)-1;
45             else ans=2*Sqrt(x);
46             printf("%lld\n",ans);
47         }else{
48             if(x==5) {puts("3");continue;}
49             if(x<5){
50                 if(x==1||x==3) {printf("-1\n");continue;}
51                 printf("%lld\n",dfs2(x));
52             }
53             else
54             {
55                 int k=Sqrt(x);k*=k;
56                 if(k==x||k+1==x){
57                     ans=2*Sqrt(x)-3;
58                 }else{
59                     ans=2*Sqrt(x)-2;
60                 }
61                 printf("%lld\n",ans+1);
62             }
63         }
64     }
65     return 0;
66 }

 

T3电压

 

题目描述:

 

老胡的某个机房中有着复杂的电路。电路由n个节点和m根细长的电阻组成,节点被标号为1~N。

 

每个节点有一个可设定的状态【高电压】或者【低电压】。每个电阻连接两个节点,只有一端是高电压,另一端是低电压的电阻才会有电流流过。两端都是高电压或者低电压的电阻不会有电流流过。

 

某天,老胡为了维护电路,选择了一根电阻,为了能让【只有这根电阻上的电流停止流动,其他M-1根电阻中都有电流流过】,需要调节各节点的电压。为了满足这个条件,能选择的电阻共有多少根?

 

现在给出电路的信息,请你输出电路维护时可以选择使其不流的电阻的个数。

 

输入:

 

第一行两个空格分隔的正整数N和M,表示电路中有N个节点和M根电阻。

 

接下来M行,第i行有两个空格分隔的正整数Ai和Bi(1<=Ai<=N,1<=Bi<=N,Ai≠Bi),表示第i个电阻连接节点Ai和节点Bi。

 

输出:

 

    输出一行一个整数,代表电路维护时可选择的使其不流的电阻个数。

 

样例输入:

 

4 4

 

1 2

 

2 3

 

3 2

 

4 3

 

样例输出:

 

2

 

样例解释:

 

可以选择第一根电阻或第四根电阻。

 

 

 

数据规模:

 

50%:N<=1000,M<=2000

 

100%: 2<=N<=10^5,1<=M<=2*10^5

 

题目转换:

给一张图,需要删掉一条边后使其成为一张二分图,且删掉的边不能是二分图上的边,求满足条件的边数。

 

思路:找在所有奇数环上,且不在偶数环上的边。 对图dfs,差分统计即可。 (图上与环有关的问题可以使用类似tarjan的做法先dfs出一颗树,再对非树边进行处理)

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<map>
 6 using namespace std;
 7 char B[1<<15],*S=B,*T=B,ch;
 8 #define getc() (S==T&&(T=(S=B)+fread(B,1,1<<15,stdin),S==T)?0:*S++)
 9 inline int read(){
10     int x=0; char ch=getc();
11     while (ch<'0'||ch>'9') {ch=getc();}
12     while (ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+ch-'0'; ch=getc();}
13     return x;
14 }
15 inline void kai(){
16     freopen("voltage.in","r",stdin);
17     freopen("voltage.out","w",stdout);
18 }const int M=2e5+5;
19 int n,m,fa[M],head[M<<1],ver[M<<1],nxt[M<<1],tot=1,d[M],odd[M],even[M],even_tot,odd_tot,ans;
20 inline void add(int x,int y){ver[++tot]=y;nxt[tot]=head[x];head[x]=tot;}
21 void dfs(int x,int l){
22     for(int i=head[x];i;i=nxt[i]) if((i^1)!=l){
23         int v=ver[i];
24         if(d[v]){
25             if(d[v]>d[x]) continue;
26             if((d[x]-d[v])&1)//奇数环 
27                 ++odd[x],--odd[v],++odd_tot;//记录差分(奇环) 
28             else ++even[x],--even[v],++even_tot;//同上(偶环) 
29         }else{
30             d[v]=d[x]+1;//访问顺序 
31             dfs(v,i);//继续向下 
32             odd[x]+=odd[v];even[x]+=even[v];
33         }
34     }
35 }
36 int main(){
37 //    kai();
38     n=read(),m=read();
39     for(int i=1;i<=m;++i){int x=read(),y=read();add(x,y),add(y,x);}
40     for(int i=1;i<=n;++i){if(!d[i]) d[i]=1,dfs(i,0),fa[i]=1;}
41     for(int i=1;i<=n;++i)if(!fa[i]&&even[i]==even_tot&&!odd[i]) ++ans;
42     if(even_tot==1) ++ans;
43     cout<<ans;
44     return 0;
45 }

 

posted @ 2019-02-13 12:57  zheng_liwen  阅读(198)  评论(0编辑  收藏  举报
/*去广告*/