zoukankan      html  css  js  c++  java
  • Codeforces Round #251 (Div. 2)AK)

    A、确定性数学计算,水,读题要快

     1 #include<iostream>
     2 #include<stdio.h>
     3 
     4 using namespace std;
     5 int N,d;
     6 int main(){
     7     while(~scanf("%d%d",&N,&d)){
     8         int cnt=0;
     9         for(int i=0;i<N;i++){
    10                 int t;
    11                 scanf("%d",&t);
    12                 cnt+=t;
    13         }
    14         if (cnt+(N-1)*10>d){
    15             printf("-1
    ");continue;
    16         }
    17         int ans=(N-1)*10/5+(d-(cnt+(N-1)*10))/5;
    18         cout<<ans<<endl;
    19 
    20     }
    21     return 0;
    22 }
    View Code

    B、贪心,章节少的课先学,排序+贪心+long long 处理细节

     1 #include<iostream>
     2 #include<stdio.h>
     3 #include<algorithm>
     4 #include<stdlib.h>
     5 
     6 using namespace std;
     7 int n,s;
     8 int a[100005];
     9 
    10 int main(){
    11     while(~scanf("%d%d",&n,&s)){
    12         for(int i=0;i<n;i++) scanf("%d",&a[i]);
    13         sort(a,a+n);
    14         long long ans=0;
    15         s++;
    16         for(int i=0;i<n;i++){
    17             if (s>1) s--;
    18             ans+=(long long)s*a[i];//在s前面加了long long 就过了,伤不起,应该是要强制转化成long long,不然后面两个int计算只保留了int部分
    19         }
    20         cout<<ans<<endl;
    21     }
    22     return 0;
    23 }
    View Code

    注意:ans+=(long long)s*a[i];//在s前面加了long long 就过了,伤不起,应该是要强制转化成long long,不然后面两个int计算只保留了int部分

    C、确定性数学证明(奇偶证明)+策略模拟 (很容易粗)

    我的写法还是不是很好,下标算来算去,这道题一定要考虑到p-k==0的情况,不然会出错,

    给自己出数据的时候,没有考虑到这个情况,比赛的时候可能就会跪了

     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <string.h>
     4 using namespace std;
     5 int n,k,p,d;//p个偶数组合
     6 int a[100006],b[100006];
     7 int main()
     8 {
     9     while(~scanf("%d%d%d",&n,&k,&p)){
    10         int cnt1=0,cnt2=0;
    11         for(int i=0;i<n;i++){
    12             int num;
    13             scanf("%d",&num);
    14             if (num % 2 == 0) a[cnt1++]=num;else b[cnt2++]=num;
    15         }
    16         int p1=p,p2=k-p;
    17         if (cnt1+cnt2/2<p1){
    18             cout<<"NO"<<endl;
    19             continue;
    20         }
    21         if (cnt1>=p1){
    22             if (cnt2<p2 || cnt2 % 2 != p2 % 2){
    23                 cout<<"NO"<<endl;
    24                 continue;
    25             }
    26             cout<<"YES"<<endl;
    27             if (p2>0){
    28                 for(int i=0;i<p1;i++){
    29                     cout<<1<<" "<<a[i]<<endl;
    30                 }
    31                 cnt1=cnt1-p1;
    32                 cout<<cnt1+(cnt2-p2)+1<<" ";
    33                 for(int i=p1;i<p1+cnt1;i++){
    34                     cout<<a[i]<<" ";
    35                 }
    36                 for(int i=0;i<(cnt2-p2)+1;i++){
    37                     if (i==cnt2-p2){
    38                         cout<<b[i]<<endl;
    39                     }else cout<<b[i]<<" ";
    40                 }
    41                 for(int i=cnt2-p2+1;i<cnt2;i++){
    42                      cout<<1<<" "<<b[i]<<endl;
    43                 }
    44             }else{
    45                 cout<<cnt1-p1+1+cnt2;
    46                 for(int i=0;i<cnt1-p1+1;i++) cout<<" "<<a[i];
    47                 for(int i=0;i<cnt2;i++) cout<<" "<<b[i];
    48                 cout<<endl;
    49                 for(int i=cnt1-p1+1;i<cnt1;i++){
    50                     cout<<1<<" "<<a[i]<<endl;
    51                 }
    52             }
    53 
    54             continue;
    55         }else {
    56             if (cnt2-(p1-cnt1)*2<p2 || (cnt2-(p1-cnt1)*2) % 2 != p2 %2 ){
    57                 cout<<"NO"<<endl;
    58                 continue;
    59             }
    60             cout<<"YES"<<endl;
    61             for(int i=0;i<cnt1;i++){
    62                 cout<<1<<" "<<a[i]<<endl;
    63             }
    64 
    65             d=0;
    66             if (p2>0){//这里是个大坑
    67                 for(int i=cnt1;i<p1;i++){
    68                     cout<<2<<" "<<b[d++]<<" "<<b[d++]<<endl;
    69                 }
    70             }else {//p2==0
    71                 for(int i=cnt1;i<p1-1;i++){
    72                     cout<<2<<" "<<b[d++]<<" "<<b[d++]<<endl;
    73                 }
    74                 cout<<cnt2-d<<" ";
    75                 for(int i=d;i<cnt2;i++){
    76                     if (i==cnt2-1) cout<<b[i]<<endl;else cout<<b[i]<<" ";
    77                     d++;
    78                 }
    79             }
    80             if (cnt2==d) continue;
    81             if (cnt2 - d > p2){
    82 
    83                 cout<<cnt2-d-p2+1<<" ";
    84                 for(int i=d;i<cnt2-p2+1;i++){
    85                     if (i==cnt2-p2){
    86                         cout<<b[i]<<endl;
    87                     }else {
    88                         cout<<b[i]<<" ";
    89                     }
    90                 }
    91                 for(int i=cnt2-p2+1;i<cnt2;i++) cout<<1<<" "<<b[i]<<endl;
    92             }else {//cnt2-d==p2
    93                 for(int i=d;i<cnt2;i++) cout<<1<<" "<<b[i]<<endl;
    94             }
    95         }
    96     }
    97     return 0;
    98 
    99 }
    View Code

     D、三分搜索+贪心+枚举(也可以排序+二分搜索(优化1/2的常数))

    题目描述:给定A数组,n个数,给定B数组,m个数,

    定义操作:一次任选数组,任选一个元素,可以增大或减少;

    求一个最小操作数,使得改变后,A中最小的元素a大于等于B中最大的元素b。

    方法就是上面所说的:

    1、三分F(X):假设最终a=b=x,注意a和b肯定相等,因为我们是向中间取数的。不等没有相等步数少。

    这样能确定x的范围,min(A)到max(B),因为我们肯定是增大A中元素,减小B中元素。

    但是我不能证明是凹性的函数啊!!!

    2、选定x,贪心的策略就定下来了:

    if (a[i]<x) ans+=x-a[i];//尽可能用最小的步数达成目的

    3、三分写法再总结:

    (1)用t控制次数,不写while

    (2)最终在[l,r]的范围内找到极值

    (3)注意画图,尽可能地包含极值点

    下面是别人的证明:

     1 #include<iostream>
     2 #include<stdio.h>
     3 #include<algorithm>
     4 #include<stdlib.h>
     5 #define LL long long
     6 using namespace std;
     7 int n,m;
     8 LL a[100005],b[100005];
     9 LL F(LL x)
    10 {
    11     //将A数组中的变成至少为x;(增加)
    12     LL ans=0;
    13     for(int i=0; i<n; i++) //可二分优化
    14     {
    15         if (a[i]<x) ans+=x-a[i];
    16     }
    17     //将A数组中的变成最多为x;(减少)
    18     for(int i=0; i<m; i++)
    19     {
    20         if (b[i]>x) ans+=b[i]-x;
    21     }
    22     return ans;
    23 }
    24 int main()
    25 {
    26 //    freopen("out.txt","w",stdout);
    27     while(~scanf("%d%d",&n,&m))
    28     {
    29         LL Min=1e12,Max=-1;
    30         for(int i=0; i<n; i++)
    31         {
    32             scanf("%I64d",&a[i]);
    33             Min=min(Min,a[i]);
    34         }
    35         for(int i=0; i<m; i++)
    36         {
    37             scanf("%I64d",&b[i]);
    38             Max=max(Max,b[i]);
    39         }
    40         sort(a,a+n);
    41         sort(b,b+m);
    42         LL l=Min-1,r=Max+1;
    43         for(int i=0; i<100; i++)
    44         {
    45             int m1=l+(r-l)/3,m2=r-(r-l)/3;
    46             if (F(m1)<F(m2)) r=m2;
    47             else l=m1;
    48         }
    49         LL ans=F(l);
    50         for(LL i=l;i<=r;i++) ans=min(ans,F(i));
    51         cout<<ans<<endl;
    52     }
    53     return 0;
    54 }
    View Code

     E、dp(关键是记忆化的思想)+乘法逆(数学考得好啊)

    ps:题解:http://codeforces.com/blog/praveen123

    推导过程太精妙了

    DP递推的方法:

     1 #include <iostream>
     2 #include <string.h>
     3 #include <stdio.h>
     4 #include <vector>
     5 #include <map>
     6 #define LL long long
     7 #define Mod 1000000007
     8 using namespace std;
     9 //LL d[100005];//局部记忆化
    10 //int dcas[100005],cas ;
    11 LL Jie[100005];
    12 LL inv[100005];
    13 typedef pair<int,int>PAIR;
    14 map<PAIR,int>MAP;
    15 vector<int>Pri[100005];//使用变长数组,预处理约数
    16 LL pow_mod(LL x,LL n){
    17     LL ans=1;
    18     while(n){
    19         if (n & 1) ans =( ans * x ) % Mod;
    20         x = (x*x) % Mod;
    21         n=n/2;
    22     }
    23     return ans;
    24 }
    25 void init(){
    26 //    memset(dcas,0,sizeof(dcas));
    27     MAP.clear();
    28     Jie[0]=1;
    29     for(int i=1;i<=100000;i++) Jie[i]=(Jie[i-1]*i) % Mod;
    30     for(int i=0;i<=100000;i++) inv[i]=pow_mod(Jie[i],Mod-2);
    31 
    32     for(int i=1;i<=100000;i++) Pri[i].clear();
    33     for(int i=2;i<=100000;i++){//类似于筛选法,为每个数填上约数
    34         for(int j=i;j<=100000;j+=i){
    35             Pri[j].push_back(i);
    36         }
    37     }
    38     return ;
    39 }
    40 LL calC(int n,int r){//C=n!/(r! * (n-r)!)
    41     return ( Jie[n] * inv[r] % Mod )*inv[n-r] % Mod;
    42 }
    43 LL dp(int n,int f){
    44     if (n<f) return 0;
    45     if (n==f) return 1;
    46     PAIR Key=make_pair(n,f);
    47     if(MAP.count(Key)) return MAP[Key];
    48 //    if (dcas[n]==cas) return d[n];
    49 //    dcas[n]=cas;//这也是一种很好的办法,,兼顾空间(省去cas标记)、初始化用时、子结构用时
    50     //但是面对极端重复数据就跪了
    51     LL ans=calC(n-1,f-1);//得到C(n-1,f-1) //隔板法
    52     LL sum=0;
    53     for (int i=0;i<(int)Pri[n].size();i++){
    54         int k=Pri[n][i];
    55         sum+=dp(n/k,f);
    56         sum = sum % Mod;
    57     }
    58     ans=(ans-sum + Mod) % Mod;
    59     MAP[Key]=ans;
    60     return ans;
    61 }
    62 int main(){
    63     init();
    64     int n,f,t;
    65     scanf("%d",&t);
    66     while(t--){
    67         scanf("%d%d",&n,&f);
    68         if (n<f){
    69             puts("0");
    70             continue;
    71         }
    72         LL ans=dp(n,f);
    73         printf("%I64d
    ",ans);
    74     }
    75     return 0;
    76 }
    View Code
  • 相关阅读:
    搭建springCloud网关zuul
    springboot添加https
    SpringBoot上传文件,经过spingCloud-Zuul,中文文件名乱码解决办法
    springboot mongodb jpa常用方法整理
    springboot拦截中自动注入的组件为null问题解决方法
    springboot JPA mysql
    转载Spring Data JPA 指南——整理自官方参考文档
    springboot带有进度条的上传
    HTTP请求示例
    http的N种请求
  • 原文地址:https://www.cnblogs.com/little-w/p/3769864.html
Copyright © 2011-2022 走看看