A:水题,根据题目意思模拟即可
#include <iostream> #include <bits/stdc++.h> using namespace std; typedef long long ll; int st[10005],prime[10005],cnt; int vis[105]; int a[305]; void ola() { for(int i=2;i<=1000000;i++) { if(st[i]==0) prime[cnt++]=i; for(int j=0;j<=cnt&&j*prime[i]<=1000000;j++) { st[i*prime[j]]=1; if(i%prime[j]==0) break; } } } ll gcd(ll a,ll b) { return b==0?a:gcd(b,a%b); } ll qpow(ll a,ll b,ll mod) { ll ans=1; while(b) { if(b&1) ans=ans*a%mod; a=a*a%mod; b>>=1; } return ans % mod; } int main() { ios::sync_with_stdio; cin.tie(0);cout.tie(0); int t; cin >> t; while(t--) { int n; cin >> n; memset(a,0,sizeof(a)); for(int i=1;i<=n;i++) cin >> a[i]; int k=n; int cnt=1; int tmp=1; while(tmp<=n) { if(tmp%2) cout << a[cnt++] <<" "; else cout << a[k--] << " "; tmp++; } cout << endl; } return 0; }B:删除一段连续字符判断剩下的是否是“2020”,YES就6种情况
#include <iostream> #include <bits/stdc++.h> using namespace std; typedef long long ll; int st[10005],prime[10005],cnt; int vis[105]; int a[305]; void ola() { for(int i=2;i<=1000000;i++) { if(st[i]==0) prime[cnt++]=i; for(int j=0;j<=cnt&&j*prime[i]<=1000000;j++) { st[i*prime[j]]=1; if(i%prime[j]==0) break; } } } ll gcd(ll a,ll b) { return b==0?a:gcd(b,a%b); } ll qpow(ll a,ll b,ll mod) { ll ans=1; while(b) { if(b&1) ans=ans*a%mod; a=a*a%mod; b>>=1; } return ans % mod; } int main() { ios::sync_with_stdio; cin.tie(0);cout.tie(0); int t; cin >> t; while(t--) { int n; cin >> n; string s; cin >> s; if (s == "2020" ||(s[0]=='2'&&s[1]=='0'&&s[2]=='2'&&s[3]=='0')||(s[0] == '2' && s[n - 1] == '0' && s[n - 2] == '2' && s[n - 3] == '0') ||(s[0] == '2' && s[1] == '0' && s[n - 2] == '2' && s[n - 1] == '0') ||(s[0] == '2' && s[1] == '0' && s[2] == '2' && s[n - 1] == '0')||(s[n-1]=='0'&&s[n-2]=='2'&&s[n-3]=='0'&&s[n-4]=='2')) cout << "YES" << endl; else cout << "NO" << endl; } return 0; }C:输入一个数X,问x最小能用哪个数上的每位数之和(每位数不相同)表示,如果没有这样的数输出-1. 如果x大于45直接输出-1,优先取0~9中大的数这样保证数的位数最小,然后排序输出
#include <iostream> #include <bits/stdc++.h> using namespace std; typedef long long ll; int st[10005],prime[10005],cnt; int vis[105]; int a[305]; void ola() { for(int i=2;i<=1000000;i++) { if(st[i]==0) prime[cnt++]=i; for(int j=0;j<=cnt&&j*prime[i]<=1000000;j++) { st[i*prime[j]]=1; if(i%prime[j]==0) break; } } } ll gcd(ll a,ll b) { return b==0?a:gcd(b,a%b); } ll qpow(ll a,ll b,ll mod) { ll ans=1; while(b) { if(b&1) ans=ans*a%mod; a=a*a%mod; b>>=1; } return ans % mod; } int main() { ios::sync_with_stdio; cin.tie(0);cout.tie(0); int t; cin >> t; while(t--) { int x; cin >> x; vector<int>v; int cnt=9; while (x >= 10&&cnt) { v.push_back(cnt); x -= cnt--; } if(x>45) cout << -1 << endl; else if(x) { int tmp=(1+cnt)*cnt/2; if (x>tmp) cout << -1 << endl; else { int temp=cnt; while(x != 0) { if (x >= temp) v.push_back(temp), x -= temp; temp--; } sort(v.begin(), v.end()); vector<int>::iterator it = v.begin(); for(; it != v.end(); ++it) { cout<<(*it); } cout << endl; } } } return 0; }D:一个数组,每次能让ai加到a(i+1)或者a(i-1),问最少多少次让数组中元素都相等。最后数组元素之和sum肯定不变,且每个元素都是sum的因子,那筛出sum的所有因子,从小到大模拟一遍即可。
#include <iostream> #include <bits/stdc++.h> #define INF 0x3f3f3f3f using namespace std; typedef long long ll; int st[10005],prime[10005],cnt; int vis[105]; ll a[3005]; void ola() { for(int i=2;i<=1000000;i++) { if(st[i]==0) prime[cnt++]=i; for(int j=0;j<=cnt&&j*prime[i]<=1000000;j++) { st[i*prime[j]]=1; if(i%prime[j]==0) break; } } } ll gcd(ll a,ll b) { return b==0?a:gcd(b,a%b); } ll qpow(ll a,ll b,ll mod) { ll ans=1; while(b) { if(b&1) ans=ans*a%mod; a=a*a%mod; b>>=1; } return ans % mod; } int main() { ios::sync_with_stdio; cin.tie(0);cout.tie(0); ll t; cin >> t; while (t--) { ll n; cin >> n; memset(a,0,sizeof(a)); ll sum=0; for (ll i = 1; i <= n; i++) { cin >> a[i]; sum+=a[i]; } vector<ll>v; for(ll i=1;i*i<=sum;i++) { if(sum%i==0) { v.push_back(i); if(i*i!=sum) v.push_back(sum/i); } } sort(v.begin(),v.end()); ll flag1=1,flag2=0; for(ll i=0;i<v.size();i++) { ll summ=0; flag1=1; for(ll j=1;j<=n;j++) { summ+=a[j]; if(summ==v[i]) summ=0; if(summ>v[i]) { flag1=0; break; } } if(flag1) { cout << n-sum/v[i] << endl; flag2=1; break; } } if(flag2==0) cout << n-1 << endl; } return 0; }E1:从n各数中选三个数,保证三个数中最大值减最小值小于等于2。排序+lower_bound。从第三个数开始遍历,每次去找比这个数小2的数,得到位置,即可通过组合数算出。
别用memset初始化,开始没注意,一直tle9,删了秒过
2020/12/21
#include <iostream> #include <bits/stdc++.h> #define INF 0x3f3f3f3f using namespace std; typedef long long ll; int st[10005],prime[10005],cnt; int vis[105]; ll a[200005]; void ola() { for(int i=2;i<=1000000;i++) { if(st[i]==0) prime[cnt++]=i; for(int j=0;j<=cnt&&j*prime[i]<=1000000;j++) { st[i*prime[j]]=1; if(i%prime[j]==0) break; } } } ll gcd(ll a,ll b) { return b==0?a:gcd(b,a%b); } ll qpow(ll a,ll b,ll mod) { ll ans=1; while(b) { if(b&1) ans=ans*a%mod; a=a*a%mod; b>>=1; } return ans % mod; } int main() { ios::sync_with_stdio; cin.tie(0);cout.tie(0); int t; cin >> t; while(t--) { ll n; cin >> n; for(ll i=1;i<=n;i++) cin >> a[i]; sort(a+1,a+1+n); ll ans=0; for(ll i=3;i<=n;i++) { ll pos=lower_bound(a+1,a+1+n,a[i]-2)-a; ll t=i-pos; if(t<2) continue; else { ans+=(t-1)*(t)/2; } } cout << ans << endl; } return 0; }要下课了,剩下E2和F抽时间再写吧
2020/12/21
E2 题目意思和E1一样就是没限定m和k,再加个取模。费马小定理求逆元+组合数,也可以用lucas。
#include <iostream> #include <bits/stdc++.h> #define INF 0x3f3f3f3f #define MOD 1000000007 using namespace std; typedef long long ll; int st[10005],prime[10005],cnt; int vis[105]; ll a[200005]; ll fac[200005],inv[200005]; void ola() { for(int i=2;i<=1000000;i++) { if(st[i]==0) prime[cnt++]=i; for(int j=0;j<=cnt&&j*prime[i]<=1000000;j++) { st[i*prime[j]]=1; if(i%prime[j]==0) break; } } } ll gcd(ll a,ll b) { return b==0?a:gcd(b,a%b); } ll qpow(ll a,ll b) { ll ans=1; while(b) { if(b&1) ans=ans*a%MOD; a=a*a%MOD; b>>=1; } return ans % MOD; } void init() { fac[0]=inv[0]=1; for(int i=1;i<200005;i++) { fac[i]=(fac[i-1]*i)%MOD;//求阶乘 inv[i]=qpow(fac[i],MOD-2);//费马小定理求逆元 } } ll C(ll a,ll b) { if(a<b||b<0) return 0; return (fac[a]*inv[b]%MOD)*inv[a-b]%MOD; } int main() { ios::sync_with_stdio; cin.tie(0);cout.tie(0); int t; cin >> t; init(); while(t--) { int n,m,k; cin >> n >> m >> k; for(int i=1;i<=n;i++) cin >> a[i]; sort(a+1,a+1+n); ll ans=0; int l=1; for(int r=m;r<=n;r++) { while(a[r]-a[l]>k) l++;//a[l]太小 if(r-l+1<m) continue;//不够m个数 ans=(ans+C(r-l,m-1))%MOD;//确定当前最大值为a[r],再从剩下的[l,r-1](即r-1-l+1=r-l)取m-1个数 } cout << ans << endl; } return 0; }F:给你n个二元组,代表线段的左右端点,问最少删几条线段,使得剩下当中存在一个线段与所有剩下的所有线段都有交集。最多删除n-1次,我们要删除的线段是它的右端点比当前该线段左端点小,左端点比当前线段右端点大。二分左端点和右端点。每次比较取最小值即可。
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int MAXN = 10005; const int N = 200005; int st[MAXN+5],prime[MAXN+5],cnt; /*void ola() { for(int i=2;i<=MAXN;i++) { if(!st[i]) prime[cnt++]; for(int j=0;j<=cnt&&i*prime[j]<=MAXN;j++) { st[i*prime[j]]=1; if(i%prime[j]) break; } } } ll gcd(ll a, ll b) { return b==0?a:gcd(b,a%b); }*/ pair<int,int>p[N]; int ls[N],rs[N]; int main() { //ios::sync_with_stdio; //cin.tie(0);cout.tie(0); int t; cin >> t; while(t--) { int n; cin >> n; for(int i=1;i<=n;i++) { int l,r; cin >> l >> r; p[i]=make_pair(l,r); ls[i]=l; rs[i]=r; } sort(ls+1,ls+1+n); sort(rs+1,rs+1+n); ll ans = n-1; for(int i=1;i<=n;i++) { ll dl=lower_bound(rs+1,rs+1+n,p[i].first)-rs-1; ll dr=ls+n+1-upper_bound(ls+1,ls+1+n,p[i].second); ans = min(ans, dl+dr); } cout << ans << endl; } return 0; }