Wannafly挑战赛6 A(二分)B(dfs)C(公式推导)E(技巧)

来源:互联网 发布:工业进销存软件免费版 编辑:程序博客网 时间:2024/05/12 12:48

A题:

题目描述

多次查询[l,r]范围内的完全平方数个数

定义整数x为完全平方数当且仅当可以找到整数y使得y*y=x

输入描述:

第一行一个数n表示查询次数之后n行每行两个数l,r

输出描述:

对于每个查询,输出一个数表示答案
示例1

输入

51 31 42 44 41 1000000000

输出

121131622

备注:

n <= 1000000<= l <= r <= 1000000000


题解:

给出的查询次数很多,故不能暴力枚举,很容易想到用二分

最后注意 0 也是平方数,并且二分查找得到的数字并不一定在区间内部


#include<math.h>#include<stdio.h>#include<algorithm>using namespace std; int a[40000],len;void init(){    len=sqrt(1000000000.0)+1;    for(int i=1;i<=len;i++)        a[i]=i*i;} int binary_search(int key){    int left=0,right=len,mid,ans;    while(left<=right){        mid=(left+right)/2;        if(a[mid]<=key) ans=mid,left=mid+1;        else            right=mid-1;    }    return ans;} int main(){    init();    int n,l,r;    //freopen("in.txt","r",stdin);    scanf("%d",&n);    while(n--)    {        scanf("%d%d",&l,&r);        int x=binary_search(l);        int y=binary_search(r);        int ans=y-x+1;        int t=sqrt(l*1.0);        if(t*t!=l) ans--;        printf("%d\n",ans);    }    return 0;}


B题:

题目描述

你在打比赛,这场比赛总共有12个题

对于第i个题,你的队伍有a[i]的几率解决她

如果解决不了她呢?

由于所有人讨论的都很大声

所以你有b[i]的概率从左边那个队那里听会这个题的做法

有c[i]的概率从右边那个队那里听会这个题的做法

请问最终你们队伍解出0-12题的概率分别是多少

输入描述:

第一行12个数表示a[1] -> a[12]第二行12个数表示b[1] -> b[12]第三行12个数表示c[1] -> c[12]

输出描述:

输出13行,第i行表示解出i-1题的概率保留6位小数
示例1

输入

0.20 0.30 0.37 0.40 0.45 0.50 0.57 0.60 0.75 0.76 0.77 0.830.85 0.88 0.90 0.94 0.100 0.104 0.105 0.107 0.115 0.120 0.122 0.1250.128 0.130 0.134 0.140 0.149 0.150 0.152 0.155 0.170 0.183 0.203 0.240

输出

0.0000000.0000000.0000000.0000110.0001600.0015080.0096200.0419380.1241530.2437730.3019600.2124530.064424

题解:

看清楚题意就很容易做,题目求做出来0 个题目的概率,到做出来12个题目的概率分别是多少

先计算出每一道题目做不出的概率:自己做不出*听不懂两边的人的题解

然后dfs暴力枚举当做出来 i 道题目的概率即可


#include<stdio.h>#define maxn 20double a[maxn],b[maxn],c[maxn],d[maxn];; double dfs(int now,int num){    double ans=1;    if(now==13&&num) return 0;    if(now==13) return ans;    if(num==0){        for(int i=now;i<=12;i++)            ans*=(1-d[i]);        return ans;    }    return ans*(dfs(now+1,num-1)*d[now]+dfs(now+1,num)*(1-d[now]));} int main(){    //freopen("in.txt","r",stdin);    for(int i=1;i<=12;i++)        scanf("%lf",&a[i]);    for(int i=1;i<=12;i++)        scanf("%lf",&b[i]);    for(int i=1;i<=12;i++)        scanf("%lf",&c[i]);     double ans=1;    for(int i=1;i<=12;i++)        d[i]=1-(1-a[i])*(1-b[i])*(1-c[i]),ans*=(1-d[i]);    printf("%0.6lf\n",ans);    for(int i=1;i<=12;i++){        ans=dfs(1,i);        printf("%0.6lf\n",ans);    }    return 0;}


C题:

题目描述

求所有长度为n的01串中满足如下条件的二元组个数:
设第i位和第j位分别位ai和aj(i<j),则ai=1,aj=0。
答案对1e9+7取模。

输入描述:

输入一个n
n <= 1018

输出描述:

输出答案对1e9+7取模
示例1

输入

3

输出

6

题解:

我们很容易发现这个 01 串中,所有2^n个数字中,0 1 数量是对等的

此时我们假设第 i 位为 0,那么前面有 i-1 位  后面有 n-i 位

那么前面有2^(i-1)个数,每一个数字有 i-1 个 0 或者 1 ,那么 1 可以出现 ( i - 1 ) * 2^( i - 1) / 2 次,即 ( i - 1 ) * 2^( i - 2)

此时已经组成了 1 0 串了(逆序正序其实都是一样的),第 i 位后面还有 2^(n-i) 个数,根据乘法原理得到 ( i - 1 ) * 2^( i - 2) * 2^(n-i)

化简得到第 i 位为 0 的时候满足条件的个数了 ( i - 1 ) * 2^( n - 2)

求个和得到 n*( n - 1 ) * 2^( n - 3)

快速幂搞一下即可


#include<stdio.h>#define LL long long#define mod 1000000007LL fast_pow(LL a,LL b){    LL ans=1;    while(b){        if(b&1) ans=ans*a%mod;        a=a*a%mod;        b>>=1;    }    return ans;}int main(){    LL n;    //freopen("in.txt","r",stdin);    while(scanf("%lld",&n)!=EOF)    {        if(n<=1)       printf("0\n");        else if(n==2)  printf("1\n");        else printf("%lld\n",n%mod*((n-1)%mod)%mod*fast_pow(2,n-3)%mod);    }    return 0;}



E题:

题目描述

对于一个数字串 s,若能找到一种将其分成左右两个非空部分 s1,s2 的方案,使得:
    1、s1,s2 均无前导零
    2、存在两个正整数 a,b,使得 b 整除 a,且 a/b=s1, a*b=s2
那么我们记这是一个合法的分法。特别地,如果一个串有两个或更多个不同的合法的分法,那么我们称这个数字串是双拆分数字串。
给定一个 n,要求构造一个长度恰为 n 的双拆分数字串。如果无解,输出 -1。

输入描述:

输入仅一行一个正整数 n(1 <= n <= 300)。

输出描述:

仅一行一个数字串或者 -1。
示例1

输入

8

输出

24419764


题意:

让你输出一个长度为n的数字,这个数字有两种或者更多的上叙的分解方法

题解:

分析得到n<=3无解

n = 4 : 1144 是一个合法解

(s1 =  1,s2 = 144,a = 12,b = 12)

(s1 = 11, s2 =  44,a = 22,b =  2)

n = 5 : 16400 是一个合法解

(s1 =  1,s2 = 6400,a = 80,b = 80)

(s1 = 16, s2 =  400,a = 80,b =  5)

之后 n = 6,7,8,,,,只需要将上面的 b 乘以 10 即可,输出即为答案


#include<stdio.h>int main(){    int n;    //freopen("in.txt","r",stdin);    while(scanf("%d",&n)!=EOF)    {        if(n<=3) puts("-1");        else if(n&1){            printf("16400");            for(int i=6;i<=n;i++) printf("0");            puts("");        }        else{            printf("1144");            for(int i=5;i<=n;i++) printf("0");            puts("");        }    }    return 0;}


原创粉丝点击