D.Cirno's Perfect Equation Class
因为b能整除c,所以b是c的因数,所以枚举c的因数,然后判断a,b是否符合条件
AC代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<deque>
#include<cmath>
#include<cstdio>
#define endl '\n'
//#define int long long
using namespace std;
typedef long long ll;
int k,c,n;
int gcd(int a,int b){
if(b==0) return a;
return gcd(b,a%b);
}
bool check(int b){
int a=(c-b)/k;
if(a*k!=c-b) return false;
if(gcd(a,b)<n||!a||!b) return false;
return true;
}
void solve()
{
cin>>k>>c>>n;
int a,b;
ll cnt=0;
for(int i=1;i<=c/i;i++){
b=i;
if(c%b==0){
if(check(b)) cnt++;
if(b*b!=c&&check(c/b)) cnt++;
}
}
cout<<cnt<<endl;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t=1;
cin>>t;
while(t--)
solve();
return 0;
}
双端队列,维护cnt[1],cnt[2],cnt[3]均大于等于1,cnt[4]大于k,然后res一直对队列的个数取min
AC代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<deque>
#include<cmath>
#include<cstdio>
#define endl '\n'
//#define int long long
using namespace std;
typedef long long ll;
const int N=1e5+10;
int a[N];
int cnt[N];
int n,k;
void solve() {
cin>>n>>k;
for(int i=1;i<=n;i++) cin>>a[i];
deque<int>q;
int res=2e9;
int count=0;
int sum=0;
for(int i=1;i<=n;i++){
q.push_back(i);
cnt[a[i]]++;
count++;
if(!cnt[1]||!cnt[2]||!cnt[3]||cnt[4]<k) continue;
while(q.size()&&(a[q.front()]!=4&&cnt[a[q.front()]]>1||a[q.front()]==4&&cnt[a[q.front()]]>k)){
cnt[a[q.front()]]--;
q.pop_front();
count--;
}
res=min(res,count);
}
cout<<res<<endl;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t=1;
// cin>>t;
while(t--)
solve();
return 0;
}
如果想用q.size()的话,需要强制转化成int类型
AC代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<deque>
#include<cmath>
#include<cstdio>
#define endl '\n'
//#define int long long
using namespace std;
typedef long long ll;
const int N=1e5+10;
int a[N];
int n,k;
int cnt[10];
void solve()
{
cin>>n>>k;
for(int i=1;i<=n;i++) cin>>a[i];
deque<int>q;
int res=2e9;
for(int i=1;i<=n;i++){
q.push_back(i);
cnt[a[i]]++;
if(!cnt[1]||!cnt[2]||!cnt[3]||cnt[4]<k) continue;
while(a[q.front()]==4&&cnt[a[q.front()]]>k||a[q.front()]!=4&&cnt[a[q.front()]]>1){
cnt[a[q.front()]]--;
q.pop_front();
}
res=min(res,(int)q.size());
}
cout<<res<<endl;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t=1;
// cin>>t;
while(t--)
solve();
return 0;
}
AC代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<deque>
#include<cmath>
#include<cstdio>
#define endl '\n'
//#define int long long
using namespace std;
typedef long long ll;
const int N=210,M=1e5+10;
int a[N],b[N];
int sz[M];
int f[N][N][N];//f[i][j][k]表示在袋子尺寸为k的情况下从奶酪区间[i,j]中能获得的最大奶酪重量
int ans[N][N];//ans[id][i]表示在奶酪区间[1,i]使用前id个取奶酪的机会能获得的最大奶酪重量
int n,m;
int res;
void solve() {
cin>>n>>m;
for(int i=1; i<=n; i++) cin>>a[i]>>b[i];
for(int i=1; i<=m; i++) cin>>sz[i];
//预处理f[i][j][k],就是一个背包问题,有限制的选择,选与不选
for(int i=1; i<=n; i++) {
for(int j=i; j<=n; j++) {
for(int k=0; k<=200; k++) {
f[i][j][k]=f[i][j-1][k];
if(k>=a[j]) f[i][j][k]=max(f[i][j][k],f[i][j-1][k-a[j]]+b[j]);
}
}
}
//t表示第几次机会,原本t是从1到m的,但是当m大于n时,因为后面的袋子尺寸是越来越大的,然后每次使用袋子肯定至少拿一个(后面袋子大,如果连后面都拿不了,前面就更拿不了了)
//即当m大于n时,只用保留最后n次即可
//将t映射到从1开始,记为idx
for (int t = max(1, m - n + 1), id = 1; t <= m; t++, id++) {
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= i; j++){
//求在区间[1,i]使用前id个取奶酪的机会能获得的最大奶酪重量
//由在区间[1,j]使用前id-1个取奶酪的机会能获得的最大奶酪重量加上在袋子尺寸为sz[t]的情况下从奶酪区间[j+1,i]能获得的最大奶酪重量转移而来,取max即可
ans[id][i] = max(ans[id][i], ans[id - 1][j] + f[j + 1][i][sz[t]]);
}
}
res=max(res,ans[id][n]);
}
cout<<res<<endl;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t=1;
// cin>>t;
while(t--)
solve();
return 0;
}