[ 校内OJ ] NOIP2019模拟赛(五)

 电阻

类欧几里得算法。

如果当前所需电阻

  • 大于$1$,串联 $1$Ω 电阻
  • 小于$1$,并联 $1$Ω 电阻
 1 #include<bits/stdc++.h> 
 2 using namespace std;
 3 ll a,b,ans;
 4 int main() {
 5     cin>>a>>b;
 6     while(a>0&&b>0) {
 7         if(a>=b) ans+=a/b,a%=b;
 8         else ans+=b/a,b%=a;
 9     }
10     cout<<ans;
11 }

 

找零

已经能组合出的面值为$1$~$now$。考虑$now+1$的面值组合,必然为$0$~$now$的一个面值加上一个硬币的面值($a[tmp]$),易得$0<a[tmp]\le now+1$。选用$a[tmp]$后,能组合出的面值更新为$1$ ~ $now+a[tmp]$,($now+1$ : $now+1-a[tmp]$的组合加上$a[tmp]$,$now+2$ : $now+2-a[tmp]$的组合加上$a[tmp]$,以此类推至$now+a[tmp]$ : $now$的组合加上$a[tmp]$)。

由此可得,要用尽量少的硬币,每次选用的$a[tmp]$的值越大越好。所以我们每次二分找出面值小于等于$now+1$的硬币中面值最大的作为$a[tmp]$。

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 const int N=1e6+5;
 5 ll n,x,now,ans,a[N];
 6 
 7 int main() {
 8     x=read(),n=read(); 
 9     for(int i=1;i<=n;i++) a[i]=read();
10     sort(a+1,a+n+1); 
11     if(a[1]!=1) return puts("-1"),0;
12     while(now<x) {
13         int tmp=upper_bound(a+1,a+n+1,now+1)-a-1;
14         //在面值小于等于now+1的硬币中找面值最大的 
15         ans++,now+=a[tmp];
16     }
17     printf("%d",ans);
18 }

 

2048

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int TT=998244353,N=1e5+5;
 4 long long n,cnt,sum,p[N],f[2050];
 5 
 6 int main() {
 7     n=read();
 8     p[0]=f[0]=1;
 9     for(int i=1;i<=n;i++) {
10         int x=read();
11         p[i]=(p[i-1]<<1)%TT;
12         if(x&(x-1)) continue; //x不是2的次幂
13         cnt++;
14         for(int j=2047;j>=x;j--)
15          f[j]=(f[j]+f[j-x])%TT;
16     }
17     for(int i=0;i<2048;i++) sum+=f[i],sum%=TT;
18     printf("%lld",p[n-cnt]*(p[cnt]-sum+TT)%TT);
19 }

 

posted @ 2019-03-31 14:15  YeLingqi  阅读(195)  评论(0编辑  收藏  举报