2017NOIp模拟赛08.20

今天没听见学长说用cena不要建子文件夹,手贱建了啊啊啊然后就gg了啊,哭qwq

Ant

问题描述

  询问 1~n 中间约数个数最多的数

输入格式

  一个数 n

输出格式

  输出 1~n 中间约数个数最多的数,如果有多个输出最小的那个

样例输入

  1000

样例输出

  840

数据规模和约定

  10%的数据满足:1≤n≤5000。

  30%的数据满足:1≤n≤100000。

  100%的数据满足:1≤n≤2000000000。

题解:

  做过的原题(不太记得是哪个oj了,说不定是openjudge),好像以前第一次写的时候是直接抄的题解啊……

  很简单,首先你要会求一个数的约数个数,其结果为:所有质因数的指数加上1后的乘积。

  看到题中还有一个小小的坑:如有多组解输出最小的那个。

  这就要求我们分解质因数后,限制较小质因数的指数,必须严格大于比它大的质因数的指数。(感觉说起来好绕口啊)比如,2^3*3^1=24,2^2*3^2=36,24<36。

  证明:反证法,如果你有一个已经分解了的数,其中2的指数比3小,那你显然可以找到一个2的指数再加1,3的指数再减1的乘积。这个乘积必定比之前的小,而且计算约数的个数也和之前一样。(顺便%一下机房大佬lyy)

  最后限制一下输出。

 1 #include<iostream>
 2 #include<cmath>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cstdio>
 6 #define ll long long
 7 using namespace std;
 8 inline void Edwina()
 9 {
10     freopen("ant.in","r",stdin);
11     freopen("ant.out","w",stdout);
12 }
13 int prime_num[20]={0,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,51};
14 ll mmax,n,ans;
15 void solve(ll now,int prim,int tot,int up)//now是当前值,tot为约数的个数,up限制指数大小 
16 {
17     if(((tot==mmax)&& (now<ans))||(tot>mmax))
18         ans=now,mmax=tot;
19     //mmax=max(tot,mmax),ans=min(now,ans);
20     int nxt_up=0,l=1,sum_prim;
21     ll i=now;
22     while(nxt_up<up)
23     {
24         nxt_up++;l++;
25         if(n/i<prime_num[prim])
26             break;
27         sum_prim=tot*l;
28         i*=prime_num[prim];
29         if(i<=n)
30             solve(i,prim+1,sum_prim,nxt_up);
31     }
32 }
33 int main()
34 {
35     Edwina();
36     mmax=-1;ans=-1;
37     scanf("%lld",&n);
38     solve(1,1,1,30);
39     printf("%lld",ans);
40     fclose(stdin);
41     fclose(stdout);
42     return 0;
43 }
View Code

Red

问题描述

  桌面上有 R 张红牌和 B 张黑牌,随机打乱顺序后放在桌面上,开始一张一张地翻牌,翻到红牌得到 1 美元,黑牌则付出 1 美元。可以随时停止翻牌,在最优策略下平均能得到多少钱。

输入格式

  一行输入两个数 R、B。

输出格式

  在最优策略下平均能得到多少钱。

样例输入

  5 1

样例输出

  4.166666

数据规模和约定

  R,B<=5000

  输出答案时,小数点后第六位后的全部去掉,不要四舍五入。

题解:

  一看就是期望dp。我们定义f(i,j)为当前状态下,还有i张红牌和j张黑牌没翻的期望受益,转移时两种情况下的结果都要考虑。

  于是f[i][j]=max(0,i/(i+j)*(f[i-1][j]+1)+j/(i+j)*(f[i][j-1]-1))

  空间注意要用滚动数组。

 1 #include<iostream>
 2 #include<cmath>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cstdio>
 6 #define ans1 ((f[j-1][end]+1)*j/i)
 7 #define ans2 ((f[j][end]-1)*(i-j)/i)
 8 #define ll long long
 9 using namespace std;
10 //const int maxn=5001;
11 inline void Edwina()
12 {
13     freopen("red.in","r",stdin);
14     freopen("red.out","w",stdout);
15 }
16 double f[10009][2];//开滚动数组 
17 double mmax(double a,double b){return a>b?a:b;}
18 int main()
19 {
20     Edwina();
21     int R,B,k=0,end=1;
22     scanf("%d%d",&R,&B);
23     for(int i=1;i<=R+B;i++,end^=1,k^=1)
24     {
25         for(int j=0;j<=i&&j<=R;j++)
26         {
27             if(j==0)
28                 f[j][k]=0;
29             else
30             {
31                 if(i==j)
32                     f[j][k]=j;
33                 else
34                     f[j][k]=mmax(0,ans1+ans2);
35                     //ans1 ((f[j-1][end]+1)*j/i)
36                     //ans2 ((f[j][end]-1)*(i-j)/i)
37             }
38         }
39     }
40     printf("%.6lf\n",floor(f[R][end]*1000000)/1000000);//对于小数位的处理 
41     //ll ans=(ll)(f[R][end]*1000000);
42     //printf("%lld.%06lld\n",ans/1000000,ans%1000000);
43     fclose(stdin);
44     fclose(stdout);
45     return 0;
46 }
View Code

Alone
问题描述
  QY 以前曾经同时与一些妹子交往,妹子们之间的关系成一棵树。一开始每个妹子对他都有一个好感度。因为 QY 太神犇了,所以很多人给他出了一些题目,
他每 AC 一道 A 出给他的题目会导致以 A 为根的子树中除了 A 以外所有的妹子对他的好感度下降。

  操作 1:QY AC 了 A 出的题目导致以 A 为根的子树中除了 A 以外所有的妹子对他的好感度下降。

  操作 2: QY 想要知道以 A 为根的子树中除了 A 以外还有几个对他好感度>0 的。

  树根处的妹子编号为 0,她对 QY 的好感度可以看做是无限的。

输入格式
  第一行一个整数 N。
  代表有 N+1 个妹子,编号分别是 0~N。
  接下来 N 行每行两个整数,第一个整数表示编号为 i 的妹子的好感度 H,第二个整数表示第i个妹子在树上的父亲Fi(保证妹子i的父亲的编号小于i)
  接下来一行一个整数 Q。
  接下来 Q 行,每行一个操作。
  第一类操作读入三个参数{1,Ai,Xi}表示 QY使以 Ai 为根的子树中除了 Ai 以外所有的妹子对他的好感度下降 Xi。
  第二类操作读入两个参数{2,Ai}表示询问以 Ai 为根的子树中除了 Ai 以外有几个妹子对 QY的好感度>0。
输出格式
  对于每一个第二类操作,输出一行一个整数,表示所询问的答案。
样例输入
4
1 0
2 0
2 2
1 2
4
1 2 1
2 2
1 0 1
2 0
样例输出
1
1
数据规模和约定
  对于 30%的数据,满足 1<=N<=1000,1<=Q<=1000。
  对于另外 20%的数据,保证数据纯随机生成。
  对于 100%的数据,满足 1<=N<=10^5,1<=Q<=10^5,0<=Ai<=N,1<=Hi<=10^9,1<=Xi<=10^4,0<=Fi<i。

  emmm……先贴上fy学长的std……

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 #define N 100010
  7 using namespace std;
  8 struct treenode
  9 {
 10     int l,r,lazy,minn,sum,mid;
 11 }tree[N*4];
 12 int tot=-1,ver[N],next[N],head[N],first[N],second[N],v[N],tim=0,a,h[N],b,c,n,m,used[2];
 13 void add(int a,int b)
 14 {
 15     tot++;
 16     ver[tot]=b;
 17     next[tot]=head[a];
 18     head[a]=tot;
 19 }
 20 
 21 void build(int tr,int l,int r)
 22 {
 23     tree[tr].l=l;
 24     tree[tr].r=r;
 25     tree[tr].lazy=0;
 26     if (l==r)
 27     {
 28         tree[tr].sum=1;
 29         tree[tr].minn=h[v[l]];
 30         return;
 31     }
 32     int mid=(l+r)/2;
 33     build(tr*2,l,mid);
 34     build(tr*2+1,mid+1,r);
 35     tree[tr].minn=min(tree[tr*2].minn,tree[tr*2+1].minn);
 36     tree[tr].mid=(tree[tr].l+tree[tr].r)>>1;
 37     tree[tr].sum=tree[tr*2].sum+tree[tr*2+1].sum;
 38 }
 39 void change(int tr,int l,int r,int data)
 40 {
 41     if (tree[tr].l==l&&r==tree[tr].r)
 42     {
 43         tree[tr].lazy+=data;
 44         if (tree[tr].minn<=tree[tr].lazy)
 45         {
 46             if (tree[tr].l==tree[tr].r)
 47             {
 48                 tree[tr].sum=0;
 49                 tree[tr].minn=0x3f3f3f3f;
 50                 tree[tr].lazy=0;
 51             }
 52             else 
 53             {
 54                 change(tr*2,tree[tr].l,tree[tr].mid,tree[tr].lazy);
 55                 change(tr*2+1,tree[tr].mid+1,tree[tr].r,tree[tr].lazy);
 56                 tree[tr].lazy=0;
 57                 tree[tr].sum=tree[tr*2].sum+tree[tr*2+1].sum;
 58                 tree[tr].minn=min(tree[tr*2].minn-tree[tr*2].lazy,tree[tr*2+1].minn-tree[tr*2+1].lazy);
 59             }
 60         }
 61         return;
 62     }
 63     if (tree[tr].lazy)
 64     {
 65         change(tr*2,tree[tr].l,tree[tr].mid,tree[tr].lazy);
 66         change(tr*2+1,tree[tr].mid+1,tree[tr].r,tree[tr].lazy);
 67         tree[tr].lazy=0;
 68     }
 69     if (r<=tree[tr].mid) change(tr*2,l,r,data);
 70     else if (l>tree[tr].mid) change(tr*2+1,l,r,data);
 71     else
 72     {
 73         change(tr*2,l,tree[tr].mid,data);
 74         change(tr*2+1,tree[tr].mid+1,r,data);
 75     }
 76     tree[tr].minn=min(tree[tr*2].minn-tree[tr*2].lazy,tree[tr*2+1].minn-tree[tr*2+1].lazy);
 77     tree[tr].sum=tree[tr*2].sum+tree[tr*2+1].sum;
 78 }
 79 
 80 int ask(int tr,int l,int r)
 81 {
 82     if (tree[tr].l==l&&tree[tr].r==r) return tree[tr].sum;
 83     int mid=(tree[tr].l+tree[tr].r)/2;
 84     if (r<=mid) return ask(tr*2,l,r);
 85     else if (l>mid) return ask(tr*2+1,l,r);
 86     else return ask(tr*2,l,mid)+ask(tr*2+1,mid+1,r);
 87 }
 88 
 89 void dfs(int a)
 90 {
 91     first[a]=++tim;
 92     v[tim]=a;
 93     for (int i=head[a];i!=-1;i=next[i])
 94     dfs(ver[i]);
 95     second[a]=tim;
 96 }
 97 
 98 int main()
 99 {
100     freopen("alone.in","r",stdin);
101     freopen("alone.out","w",stdout);
102     cin>>n;
103     memset(head,-1,sizeof(head));
104     for (int i=1;i<=n;i++)
105     scanf("%d%d",&h[i],&a),add(a,i);
106     h[0]=0x3f3f3f3f;
107     dfs(0);
108     cin>>m;
109     build(1,1,n+1);
110     for (int i=1;i<=m;i++)
111     {
112         scanf("%d",&a);
113         if (a==1)
114         {
115             scanf("%d%d",&b,&c);
116             if (first[b]!=second[b]) change(1,first[b]+1,second[b],c);
117         }
118         else
119         {
120             scanf("%d",&b);
121             if (first[b]!=second[b]) printf("%d\n",ask(1,first[b]+1,second[b]));
122             else printf("0\n");
123         }
124     }
125     fclose(stdin);
126     fclose(stdout);
127     return 0;
128 }
View Code

 

转载于:https://www.cnblogs.com/Beckinsale/p/7401598.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值