A.Hcode OnlineJudge
顺序并不重要,只需要考虑个数
#include<bits/stdc++.h>
#define endl '\n'
#define mk make_pair
#define int long long
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 1e5+10;
const int mod = 998244353;
int n,m,k;
int a[N],b[N],c[N];
map<int,int>v,d;
void sovle(){
int sum=0;
cin>>n;
for(int i=0;i<n;i++) cin>>a[i],v[a[i]]++;
for(int i=1;i<=n;i++) cin>>b[i];
for(int i=0;i<n;i++) cin>>c[i],d[b[c[i]]]++;
for(auto ed:v){
sum+=d[ed.first]*ed.second;
}
cout<<sum<<endl;
}
signed main()
{
ios::sync_with_stdio(false), cin.tie(0),cout.tie(0);
int t = 1;
//cin>>t;
while (t--){
sovle();
}
return 0;
}
B.Hcode OnlineJudge
外层二进制枚举行,内层二进制枚举列,枚举到的行和列跳过,计算黑色格的个数是否等于k
#include<bits/stdc++.h>
#define endl '\n'
#define mk make_pair
#define int long long
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 1e5+10;
const int mod = 998244353;
int n,m,k;
void sovle(){
int num=0;
cin>>n>>m>>k;
char ch[n][m];
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
cin>>ch[i][j];
}
}
for(int i=0;i<(1<<n);i++){
map<int,int>v;
for(int j=0;j<n;j++){
if((i>>j)&1){
v[j]=1;
}
}
for(int j=0;j<(1<<m);j++){
map<int,int>d;
for(int u=0;u<m;u++){
if((j>>u)&1){
d[u]=1;
}
}
int sum=0;
for(int x=0;x<n;x++){
if(v[x]) continue;
for(int y=0;y<m;y++){
if(d[y]) continue;
if(ch[x][y]=='#') sum++;
}
}
if(sum==k){
num++;
}
}
}
cout<<num<<endl;
}
signed main()
{
ios::sync_with_stdio(false), cin.tie(0),cout.tie(0);
int t = 1;
//cin>>t;
while (t--){
sovle();
}
return 0;
}
C.Hcode OnlineJudge
有点烦的模拟题(恼
n只有五千,但是k有1e9。对于每个点,必定有循环节,所以我们枚举从每个点开始的情况,记录他周期的步数、周期的值和过程中的最大值。然后再模拟每个点出发的结果的最大值。
反思:模拟题,允许的话手动模拟一遍,思路要清晰,先理清再动代码
#include<bits/stdc++.h>
#define endl '\n'
#define mk make_pair
#define int long long
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 5e4+10;
const int mod = 998244353;
int n,m,k,cnt,max1=-LLONG_MAX;
int bushu[N],zhi[N],zuida[N];
//bushu数组存i点出发循环节的步数,zhi存i点出发循环节的值,zuida存i点出发一个周期过程中的最大值
void sovle(){
cin>>n>>k;
vector<int>a(n+1),b(n+1);
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=n;i++){
cin>>b[i];
}
for(int i=1;i<=n;i++){
cnt=a[i];bushu[i]=1;zhi[i]=b[cnt];zuida[i]=-1000000000;zuida[i]=max(zhi[i],zuida[i]);
while(1){
if(cnt==i) break;
bushu[i]++;cnt=a[cnt];zhi[i]+=b[cnt];zuida[i]=max(zuida[i],zhi[i]);
}
}
for(int i=1;i<=n;i++){
if(k>=bushu[i]) max1=max(max1,zuida[i]);
if(k%bushu[i]==0) {max1=max(max1,(zuida[i]+(k/bushu[i]-1)*zhi[i]));continue;}
int num=(k/bushu[i])*zhi[i];
int cntt=1,cnt1=a[i];num+=b[cnt1];max1=max(max1,num);
while(1){
if(k%bushu[i]==cntt) break;
cntt++;cnt1=a[cnt1];num+=b[cnt1];max1=max(max1,num);
}//max1=max(max1,num);
}
cout<<max1<<endl;
}
signed main()
{
ios::sync_with_stdio(false), cin.tie(0),cout.tie(0);
int t = 1;
//cin>>t;
while (t--){
sovle();
}
return 0;
}
D.Hcode OnlineJudge
用欧拉筛法处理一下1-n每个数的因子个数
#include<bits/stdc++.h>
#define endl '\n'
#define mk make_pair
#define int long long
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 1e7+10;
const int mod = 998244353;
int n,m,k;
int prime[N],d[N],num[N];
bool isprime[N];
//prime数组存质数,isprime数组存是否是质数,d数组存因子个数,num数组存i的最小因子出现次数
void Euler(){
int tot=0;
memset(isprime,1,sizeof isprime); d[1]=1;
for(int i=2;i<=n;i++){
if(isprime[i]){
prime[++tot]=i;
d[i]=2;
num[i]=1;
}
for(int j=1;j<=tot&&i*prime[j]<=n;j++){
isprime[i*prime[j]]=0;
if(i%prime[j]==0){
d[i*prime[j]]=d[i]/(num[i]+1)*(num[i]+2);
num[i*prime[j]]=num[i]+1; break;
}
else{
d[i*prime[j]]=d[i]*2;
num[i*prime[j]]=1;
}
}
}
}
void sovle(){
cin>>n;
Euler();
int sum=0;
for(int i=1;i<=n;i++){
sum+=i*d[i];
}
cout<<sum<<endl;
}
signed main()
{
ios::sync_with_stdio(false), cin.tie(0),cout.tie(0);
int t = 1;
//cin>>t;
while (t--){
sovle();
}
return 0;
}
E.Hcode OnlineJudge
从a中选x个,b中选y个,可以用任意一个c替换掉任意一个a或者b。我们可以先选最大的x个a和最大的y个b放入,然后用c替换掉小的那些最小的数。对于替换的过程,我们可以简化为直接将c全部放进去,全部取x+y个最大数就行。
证明:将大的c放入,相当于把c涂成某个颜色,那个颜色中最小的数相当于没有选中。就完成替换
#include<bits/stdc++.h>
#define endl '\n'
#define mk make_pair
#define int long long
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 1e5+10;
const int mod = 998244353;
int n,m,k,x,y;
int a[N],b[N],c[N];
void sovle(){
int ans=0;
priority_queue<int>v;
cin>>x>>y>>n>>m>>k;
for(int i=0;i<n;i++) cin>>a[i];
for(int j=0;j<m;j++) cin>>b[j];
sort(a,a+n,greater<int>());sort(b,b+m,greater<int>());
for(int i=0;i<x;i++) v.push(a[i]);
for(int i=0;i<y;i++) v.push(b[i]);
for(int i=0;i<k;i++) cin>>c[i],v.push(c[i]);
for(int i=0;i<x+y;i++) ans+=v.top(),v.pop();
cout<<ans<<endl;
}
signed main()
{
ios::sync_with_stdio(false), cin.tie(0),cout.tie(0);
int t = 1;
//cin>>t;
while (t--){
sovle();
}
return 0;
}
F.Hcode OnlineJudge
由公式的推导得 (Sj-j)%k==(Si-i)%k. (0<=j-i<k). (i<j)
那么我们预处理出每个前缀和的(Si-i)%k,从左到右遍历前缀和数组sum,用map存遍历到的结果,我们需要找到前面有几个前缀和的结果与当前前缀和的结果相同,我们还需要提前处理本身就可以满足条件的也就是v[0]==1,因为是ans先加map后加,所以没办法处理到本身就满足的情况
反思:由区间想到前缀和,公式的推导,怎么更方便地对遍历的情况处理
#include<bits/stdc++.h>
#define endl '\n'
#define mk make_pair
#define int long long
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 1e5+10;
const int mod = 998244353;
int n,m,k;
void sovle(){
cin>>n>>k;
vector<int>a(n+1),sum(n+1);
map<int,int>v;
for(int i=1;i<=n;i++){
cin>>a[i];
sum[i]=sum[i-1]+a[i];
}
for(int i=1;i<=n;i++){
sum[i]=(sum[i]-i)%k;
}
int ans=0;
v[0]=1;
for(int i=1;i<=n;i++){
if(i>=k){
v[sum[i-k]]--;
}
ans+=v[sum[i]];
v[sum[i]]++;
}
cout<<ans<<endl;
}
signed main()
{
ios::sync_with_stdio(false), cin.tie(0),cout.tie(0);
int t = 1;
//cin>>t;
while (t--){
sovle();
}
return 0;
}