2020牛客寒假算法基础集训营1

 A   honoka和格点三角形 

思路:一道规律题,考虑底为1或者2,高位2或者1的,然后去除有两边都平行于坐标轴的,注意计算的每个数都要mod

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const long long mod=1000000007;
 5 int main()
 6 {
 7     ll n,m;
 8     while(~scanf("%lld%lld",&n,&m)){
 9         ll a=(((((m%mod)-2)*(m%mod-2))%mod)*(n%mod-1)*2)%mod;
10         ll b=(((((n%mod)-2)*(n%mod-2))%mod)*(m%mod-1)*2)%mod;
11         ll c=(((m%mod*(m%mod-1))%mod)*(n%mod-2)*2)%mod;
12         ll d=(((n%mod*(n%mod-1))%mod)*(m%mod-2)*2)%mod;
13         cout<<(a+b+c+d)%mod<<endl;
14     }
15     return 0;
16 }

  B   kotori和bangdream

思路:根据期望公式来计算平均值

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int main()
 4 {
 5     double n,x,a,b;
 6     scanf("%lf%lf%lf%lf",&n,&x,&a,&b);
 7     double ss=n*a*x/100.0+n*b*(100.0-x)/100.0;
 8     printf("%.2lf\n",ss);
 9     return 0;
10 }

 D   hanayo和米饭 

思路:将数组排序后判断当前值是否是i+1即可

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn = 1e5+10;
 5  
 6 int main() {
 7  
 8     int T;
 9     scanf("%d",&T);
10     int a[maxn];
11     for(int i=0;i<T-1;i++)
12     {
13         scanf("%d",&a[i]);
14     }
15     sort(a,a+T-1);
16     bool flag=false;
17     int sum=0;
18     for(int i=0;i<T-1;i++)
19     {
20         if(a[i]!=i+1)
21         {
22             flag=true;
23            sum=a[i]-1;
24             break;
25         }
26     }
27     if(flag)
28         printf("%d\n",sum);
29     else
30         printf("%d\n",T);
31     return 0;
32 }

 E   rin和快速迭代 

思路:分解质因子即可,每个质数的指数+1之积就是因子个数

  1 #include<iostream>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<iomanip>
  5 #include<stdio.h>
  6 #include<stdlib.h>
  7 #include<math.h>
  8 #include<cstdlib>
  9 #include<set>
 10 #include<map>
 11 #include<ctime>
 12 #include<stack>
 13 #include<queue>
 14 #include<vector>
 15 #include<set>
 16 using namespace std;
 17 typedef long long ll;
 18 const ll NUM=10;//运算次数,Miller_Rabin算法为概率运算,误判率为2^(-NUM);
 19 ll t,f[100];
 20 ll mul_mod(ll a,ll b,ll n)//求a*b%n,由于a和b太大,需要用进位乘法
 21 {
 22     a=a%n;
 23     b=b%n;
 24     ll s=0;
 25     while(b)
 26     {
 27         if(b&1)
 28             s=(s+a)%n;
 29         a=(a<<1)%n;
 30         b=b>>1;
 31     }
 32     return s;
 33 }
 34 ll pow_mod(ll a,ll b,ll n)//求a^b%n
 35 {
 36     a=a%n;
 37     ll s=1;
 38     while(b)
 39     {
 40         if(b&1)
 41             s=mul_mod(s,a,n);
 42         a=mul_mod(a,a,n);
 43         b=b>>1;
 44     }
 45     return s;
 46 }
 47 bool check(ll a,ll n,ll r,ll s)
 48 {
 49     ll ans=pow_mod(a,r,n);
 50     ll p=ans;
 51     for(ll i=1;i<=s;i++)
 52     {
 53         ans=mul_mod(ans,ans,n);
 54         if(ans==1&&p!=1&&p!=n-1)
 55             return true;
 56         p=ans;
 57     }
 58     if(ans!=1) return true;
 59     return false;
 60 }
 61 bool Miller_Rabin(ll n)//Miller_Rabin算法,判断n是否为素数
 62 {
 63     if(n<2) return false;
 64     if(n==2) return true;
 65     if(!(n&1)) return false;
 66     ll r=n-1,s=0;
 67     while(!(r&1)){r=r>>1;s++;}
 68     for(ll i=0;i<NUM;i++)
 69     {
 70         ll a=rand()%(n-1)+1;
 71         if(check(a,n,r,s))
 72             return false;
 73     }
 74     return true;
 75 }
 76 ll gcd(ll a,ll b)
 77 {
 78     return b==0?a:gcd(b,a%b);
 79 }
 80 ll Pollard_rho(ll n,ll c)//Pollard_rho算法,找出n的因子
 81 {
 82     ll i=1,j,k=2,d,p;
 83     ll x=rand()%n;
 84     ll y=x;
 85     while(true)
 86     {
 87         i++;
 88         x=(mul_mod(x,x,n)+c)%n;
 89         if(y==x) return n;
 90         if(y>x) p=y-x;
 91         else p=x-y;
 92         d=gcd(p,n);
 93         if(d!=1&&d!=n) return d;
 94         if(i==k)
 95         {
 96             y=x;
 97             k+=k;
 98         }
 99     }
100 }
101 void find(ll n)//找出n的所有因子
102 {
103     if(Miller_Rabin(n))
104     {
105         f[t++]=n;//保存所有因子
106         return;
107     }
108     ll p=n;
109     while(p>=n)p=Pollard_rho(p,rand()%(n-1)+1);//由于p必定为合数,所以通过多次求解必定能求得答案
110     find(p);
111     find(n/p);
112 }
113 ll aa(ll n)
114 {
115     t=0;
116     find(n);
117     sort(f,f+t);
118     map<ll,int>q;
119     for(int i=0;i<t;i++)
120     {
121         q[f[i]]++;
122     }
123     map<ll,int>::iterator it;
124     ll ans=1;
125     for(it=q.begin();it!=q.end();it++)
126     {
127         int s=it->second;
128         ans*=1+s;
129     }
130     return ans;
131 }
132 int main()
133 {
134     
135     ll n;cin>>n;
136     ll ss=0;
137     while(1)
138     {
139         if(aa(n)==2)
140             break;
141         else
142         {
143             ss++;
144             n=aa(n);
145         }
146     }
147     printf("%lld\n",ss+1);
148     return 0;
149 }

  G   eli和字符串

思路:用队列queue【】,来存放每个字母出现的位置,一旦这个字母位置出现超过了包括k次,那么计算队列末尾-队首+1,同时pop队首,每次更新最小值

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int INF=0x3ffff;
 5 int main()
 6 {
 7     int n,k;
 8     string s;
 9     scanf("%d%d",&n,&k);
10     cin>>s;
11     bool flag=false;
12     queue<int>qu[30];
13     int ans=INF;
14     for(int i=0;i<n;i++)
15     {
16         int a=s[i]-'a';
17         qu[a].push(i);
18         if(qu[a].size()>=k)
19         {
20             flag=true;
21             ans=min(ans,i-qu[a].front()+1);
22             qu[a].pop();
23         }
24     }
25     if(!flag||ans==INF)
26         printf("-1\n");
27     else
28         printf("%d\n",ans);
29      
30     return 0;
31 }

 H   nozomi和字符串 

思路:用vector来记录0,1个数,保留每个区间数量最多的那个数,用该区间数量减去这个最多的,一旦发现值小于k,那么就说明,这个值的数量的0或1都能转化,否则就区间右移

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int INF=0x3ffff;
 5 int main()
 6 {
 7     int n,k;
 8     string s;
 9     scanf("%d%d",&n,&k);
10     cin>>s;
11     vector<int>vv(2,0);
12     int res=0,num=0;
13     for(int i=0,j=0;i<n;i++)
14     {
15         int a=s[i]-'0';
16         vv[a]++;
17         num=max(vv[a],num);
18         while(i-j+1-num>k)
19             vv[s[j++]-'0']--;
20         res=max(res,i-j+1);
21     }
22     printf("%d\n",res);
23  
24     return 0;
25 }

 

posted @ 2020-02-04 20:23  branna  阅读(186)  评论(0编辑  收藏  举报