8.19普及模拟二
就不该打那b表
\(\large{T1\ 地址} \ \ \tiny{100 pts}\)
- 去年csp-jT3阉割版(sbDragen:这哪是阉割啊 这是连腰子都噶了)
- 模拟就完了(又调半天给我去年T3 PTST整出来了)
#include <iostream>
#include <cstdio>
#include <cstring>
#define int long long
#define frer freopen("ip.in","r",stdin);
#define frew freopen("ip.out","w",stdout);
using namespace std;
string c;
int i=1,cnt;
int wr,num1,num2,num3,num4;
inline void works(int mod){
int fir=0;
while(c[i]>='0'&&c[i]<='9'){
if(fir==0&&c[i]=='0'){
wr=1;
}
if(fir==0&&c[i]!='0'){
fir=1;
}
if(mod==1)num1=num1*10+(c[i]-'0');
else if(mod==2)num2=num2*10+(c[i]-'0');
else if(mod==3)num3=num3*10+(c[i]-'0');
else if(mod==4)num4=num4*10+(c[i]-'0');
i++;
//cout << 1;
}
i--;
// cout << c << " ";
// cout << i<<" ";
if(i!=c.size()-1&&(c[i+1]!='.'||(c[i+2]<'0'||c[i+2]>'9'))){
wr=1;
}
while(i!=c.size()-1&&(c[i+1]<'0'||c[i+1]>'9')){
i++;
}
i++;
}
inline void work(){
works(1);
works(2);
works(3);
works(4);
if(num1>255){wr=1;num1=255;}
if(num2>255){wr=1;num2=255;}
if(num3>255){wr=1;num3=255;}
if(num4>255){wr=1;num4=255;}
if(wr){
printf("NO\n");
printf("%lld.%lld.%lld.%lld",num1,num2,num3,num4);
}
else printf("YES\n");
}
signed main(){
frer;
frew;
cin >> c;
c=" "+c;
work();
//printf("%s",c);
return 0;
}
\(\large{T2\ 内积} \ \ \tiny{100 pts}\)
- 给定两个数组 \(a,b\),使\(\sum_{i=1}^{n}{a_i \times b_i}\)最大
- 显然题,贪心
#include <iostream>
#include <cstdio>
#include <algorithm>
#define int long long
#define frer freopen("nj.in","r",stdin);
#define frew freopen("nj.out","w",stdout);
using namespace std;
const int Max = 1e6+10;
int n,ans;
int a[Max],b[Max];
inline int read(){
int num=0,fl=1;char c=getchar();
while(c <'0'||c >'9'){
if(c=='-') fl=-1;
c=getchar();
}
while(c >='0'&&c <= '9'){
num=(num<<3)+(num<<1)+(c^48);
c=getchar();
}
return fl*num;
}
signed main(){
frer;
frew;
n=read();
for(int i = 1;i <= n;i++){
a[i]=read();
}
for(int i = 1;i <= n;i++){
b[i]=read();
}
sort(a+1,a+n+1);
sort(b+1,b+n+1);
for(int i = 1;i <= n;i++){
ans+=a[i]*b[i];
}
printf("%lld",ans);
return 0;
}
\(\large{T3\ 翻转} \ \ \tiny{10 pts}\)
- 题意:给定一个由1和0组成的\(n\times n\)的矩形,每次可以将一个点和其上下左右四个点一同翻转。求使矩形全部为1或全部为0的最小翻转次数。
- 因为当第一行的状态确定时,其他行的状态也可以确定(每行补上一行的空),最后一行因为没有下一行所以不能确定。所以只需枚举第一行的状态,在将其他行推出来,最后检查一遍最后一行是不是全部为目标状态即可(1或0)
- 因为需要对矩形进行修改,所以需要另开一个数组进行备份。当每一次开始check时需要备份一下当期状态,check结束时还原,使dfs继续枚举下一种状态(不然之前的状态会丢失(?))
#include <iostream>
#include <cstring>
#define int long long
#define frer freopen("in.in","r",stdin);
#define frew freopen("out.out","w",stdout);
using namespace std;
const int Max = 20;
int n;
int map[Max][Max];
int mapp[Max][Max];
string s;
int ans = 0x3f3f3f3f3f3f;
inline int read(){
int num=0,fl=1;char c=getchar();
while(c<'0'||c>'9'){
if(c=='-') fl=-1;
c=getchar();
}
while(c >='0'&&c <='9'){
num=(num<<3)+(num<<1)+(c^48);
c=getchar();
}
return num*fl;
}
inline void reMake1(){
for(int i = 1;i <= n;i++){
for(int j = 1;j <= n;j++){
map[i][j]=mapp[i][j];
}
}
}
inline void reMake2(){
for(int i = 1;i <= n;i++){
for(int j = 1;j <= n;j++){
mapp[i][j]=map[i][j];
}
}
}
inline void fz(int x,int y){
map[x][y]^=1;map[x-1][y]^=1;map[x+1][y]^=1;map[x][y-1]^=1;map[x][y+1]^=1;
}
inline void check(int sum,int colr){
reMake2();
for(int i = 2;i <= n;i++){
for(int j=1;j <= n;j++){
if(map[i-1][j]!=colr){
fz(i,j);
sum++;
}
}
}
for(int i = 1;i <= n;i++)
if(map[n][i]!=colr)
return;
ans=min(ans,sum);
return;
}
inline void dfs(int step,int sum,int colr){
if(step==n){
check(sum,colr);
reMake1();
return;
}
dfs(step+1,sum,colr);
fz(1,step+1),dfs(step+1,sum+1,colr),fz(1,step+1);
}
signed main(){
frer;
frew;
n=read();
for(int i = 1;i <= n;i++){
cin>>s;
s=" "+s;
for(int j = 1;j <= n;j++){
if(s[j]=='b') mapp[i][j]=1;
else mapp[i][j]=0;
}
}
reMake1();
dfs(0,0,1);
dfs(0,0,0);
if(ans!=0x3f3f3f3f3f3f)printf("%lld",ans);
else printf("Impossible");
return 0;
}
\(\large{T4\ 阶乘} \ \ \tiny{0 pts}\)
- 题意:给定一个整数\(n\),\(a,b\in Z\),求使\(\dfrac{a!}{b!}=n\)的所有方案
- 没思路,打了个表,本来可以拿10pts的,加了个1~100000所有质数的表结果C
了TAT - 分析题目,可以将题目转化为求积为\(n\)的几个连续整数。我们就可以枚举\(a-b\)的长度,因为阶乘的增长速度很大,所以不会枚举很多,到21即可(21! 几乎可以覆盖所有整形)。
- 假设 \(a_1*a_2*a_3*a_4*a_5=n(a_1,a_2,a_3,a_4,a_5为连续的五个整数) 可以得出 a_1\thickapprox \sqrt[5]{n}(a_2 - a_5同理)\) 那么假设 \(len=a-b\), 显然可以得出 \(a\geq\sqrt[len]{n},b\leq\sqrt[len]{n}\)。
- 我们就可以枚举区间长度,令\(r=\sqrt[len]{n}\)(\(r\)的最小值),\(l=r-len+1\) 并不断调整区间位置,直至积等于\(n\)。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#define int long long
#define frer freopen("in.in","r",stdin);
#define frew freopen("out.out","w",stdout);
using namespace std;
const int Max = 1e6;
int T;
int n,sum,cnt;
struct node{
int a,b;
}ans[Max];
inline int read(){
int num=0,fl=1;char c=getchar();
while(c <'0'||c >'9'){
if(c=='-') fl=-1;
c=getchar();
}
while(c >='0'&&c <= '9'){
num=(num<<3)+(num<<1)+(c^48);
c=getchar();
}
return fl*num;
}
signed main(){
frer;
frew;
T=read();
while(T--){
cnt=0;
n=read();
if(n==1){
printf("-1\n");
continue;
}
for(int len = 2;len <= 21;len++){
for(int r= pow((double)(n),1.0/(double)(len));;r++){
int l=r-len+1;
sum=1;
for(int i = l;i <= r;i++) sum*=i;
if(sum>n) break;
if(sum==n&&l-1!=0){
ans[++cnt]=(node){r,l-1};
}
}
}
printf("%lld\n",cnt+1);
for(int i = cnt;i >= 1;i--){
printf("%lld %lld\n",ans[i].a,ans[i].b);
}
printf("%lld %lld\n",n,n-1);
}
return 0;
}
$\large{总结} $
少整点没用的
有点思维含量的题就挂