2023/3/3
方格分割
按方格去分割很难判断是否分出来的2部分相等
从点的角度去走,为了使得分割的2部分相等则分割线一定会经过中心点(3,3) (左上角为(0,0))
从中心点开始2个点同时往2个反方向走,当遇上边界时即为完成一次切割。
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
typedef long long ll;
bool vis[10][10];
int sx[4]={0,0,1,-1},sy[4]={1,-1,0,0},ans;
void dfs(int x,int y){
if(x==0||x==6||y==0||y==6){
ans++;
return ;
}
for(int i=0;i<4;i++){
int xx=x+sx[i],yy=y+sy[i];
if(vis[xx][yy])continue;
vis[xx][yy]=true;
vis[6-xx][6-yy]=1;
dfs(xx,yy);
vis[xx][yy]=false;
vis[6-xx][6-yy]=0;
}
}
void slove(){
vis[3][3]=true;
dfs(3,3);
cout<<ans/4<<endl;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int T=1;
// cin>>T;
while(T--){
slove();
}
return 0;
}
包子凑数
首先解决是否INF的问题
若给出的 A为{2,4,6},gcd(2,4,6)=2,他们得出的只能是2的倍数
只有 A序列中的最大公约数为1时候才不会有无限多个凑不出来的数
在有限个凑的出来的问题中 N<=100 , Ai<=100可以得出最大的情况下包子为10000
可以看成是容量为10000背包问题去解决
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
typedef long long ll;
int dp[10005];
void slove(){
int n;
cin>>n;
vector<int>a(n);
for(auto &x:a)cin>>x;
sort(a.begin(),a.end());
int g=a[0];
for(auto x:a)g=__gcd(g,x);
if(g!=1){
cout<<"INF"<<endl;
return ;
}
dp[0]=1;
for(auto x:a){
for(int i=x;i<=10000;i++){
dp[i]|=dp[i-x];
}
}
int ans=0;
for(int i=1;i<=10000;i++){
if(!dp[i])ans++;
}
cout<<ans<<endl;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int T=1;
// cin>>T;
while(T--){
slove();
}
return 0;
}
分巧克力
二分最大可能的边长,判断该边长是否可以切出至少k个巧克力
每个巧克力的切割个数为 (h/mid)*(w/mid)
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
#define f first
#define s second
typedef long long ll;
int n,k;
bool check(int m,vector<pair<int,int>>&a){
int now=0;
for(auto [x,y]:a){
now+=(x/m)*(y/m);
if(now>=k)return true;
}
return now>=k;
}
void slove(){
cin>>n>>k;
vector<pair<int,int>>a(n);
int l=1,r=1e5;
for(auto &[x,y]:a)cin>>x>>y;
while(l<r){
int mid=l+r+1>>1;
if(check(mid,a))l=mid;
else r=mid-1;
}
cout<<l<<endl;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int T=1;
// cin>>T;
while(T--){
slove();
}
return 0;
}
购物单
5200
等差素数列
先将素数筛出来然后暴力
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
typedef long long ll;
const int N=1e6+5;
bool vis[N];
int pr[N],cnt;
void getpr(int n){
vis[1]=true;
for(int i=2;i<=n;i++){
if(!vis[i])pr[++cnt]=i;
for(int j=1;j<=cnt&&pr[j]*i<=n;j++){
vis[pr[j]*i]=true;
}
}
}
void slove(){
for(int i=1;i<=cnt;i++){
for(int j=1;j<=10000;j++){
bool p=true;
for(int k=0;k<10;k++){
if(!vis[pr[i]+j*k])continue;
p=false;
break;
}
if(p){
cout<<j<<endl;
return ;
}
}
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int T=1;
getpr(1000000);
// cin>>T;
while(T--){
slove();
}
return 0;
}
承压计算
类似杨辉三角的往下传递
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
typedef long long ll;
double a[35][35];
void slove(){
for(int i=1;i<30;i++){
for(int j=1;j<=i;j++){
cin>>a[i][j];
}
}
double res=2086458231;
for(int i=1;i<=30;i++){
for(int j=1;j<=i;j++){
a[i][j]+=a[i-1][j]*1.0/2.0+a[i-1][j-1]*1.0/2.0;
}
}
double mn=1e9,mx=0;
for(int i=1;i<=30;i++){
mn=min(mn,a[30][i]);
mx=max(mx,a[30][i]);
}
res=res/mn*mx;
// printf("%lf\n",res);
cout<<"72665192664"<<endl;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int T=1;
// cin>>T;
while(T--){
freopen("sj.txt","r",stdin);
slove();
fclose(stdin);
}
return 0;
}
日期问题
枚举19600101->20591231之间的所有数,判断是否合法
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
typedef long long ll;
int a,b,c;
int mh[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
bool rn(int year){
return year%4==0&&year%100!=0||year%400==0;
}
bool check(int aa,int bb,int cc){
return a==aa&&b==bb&&c==cc;
}
void slove(){
scanf("%02d/%02d/%02d",&a,&b,&c);
for(int i=19600101;i<=20591231;i++){
int y=i/10000,m=i%10000/100,d=i%100;
if(rn(y))mh[2]=29;
else mh[2]=28;
if(m<1||m>12)continue;
if(d>mh[m]||d<1)continue;
if(check(y%100,m,d)||check(m,d,y%100)||check(d,m,y%100)){
printf("%04d-%02d-%02d\n",y,m,d);
}
}
}
int main(){
// ios::sync_with_stdio(false);
// cin.tie(0);cout.tie(0);
int T=1;
// cin>>T;
while(T--){
slove();
}
return 0;
}
k倍区间
当一个数 a%k=0 (a!=0)时,则a是k的倍数
当一个区间和 sum%k=0 时,这个区间和sum是k的倍数
因为 1<=ai<=1000000 是正整数
所以从左到右前缀和一定是递增的
若当前的前缀和为 sum%k 减去之前也为 sum%k 的前缀和即为 0 (k的倍数)
用一个map统计之前 sum%k出现的次数,跑一遍数组统计k倍区间的个数
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
#define int long long
typedef long long ll;
void slove(){
int n,k;
cin>>n>>k;
vector<int>a(n);
for(auto &x:a){
cin>>x;
x%=k;
}
int sum=0;
int ans=0;
map<int,int>mp;
mp[0]=1;
for(auto x:a){
sum+=x;
sum%=k;
ans+=mp[sum];
mp[sum]++;
}
cout<<ans<<endl;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int T=1;
// cin>>T;
while(T--){
slove();
}
return 0;
}