#include
using namespace std;
bool f(int x){
if(x%4==0&&x%100!=0)return 1;
if(x%400==0)return 1;
return 0;
}
int main(){
int n;
while(scanf("%d",&n)!=EOF){
if(f(n))printf("yes\n");
else printf("no\n");
}
return 0;
}
#include
using namespace std;
int main(){
for(int i=0;i<(1<<5);i++){
int x=i;
for(int j=4;j>=0;j--){
printf("%d",(x>>j)&1);
}
printf("\n");
}
return 0;
}
#include
using namespace std;
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
printf("%c",'A'+abs(i-j));
}
printf("\n");
}
return 0;
}
#include
using namespace std;
#define maxn 100052
int a[maxn];
int main(){
int n;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
int ans1=-maxn,ans2=maxn,ans=0;
for(int i=0;i<n;i++){
ans1=max(ans1,a[i]);
ans2=min(ans2,a[i]);
ans+=a[i];
}
printf("%d\n%d\n%d\n",ans1,ans2,ans);
return 0;
}
#include
using namespace std;
#define maxn 100052
int a[maxn];
int main(){
int n;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
int x;
scanf("%d",&x);
//int ans1=-maxn,ans2=maxn,ans=0;
for(int i=0;i<n;i++){
if(a[i]==x){
printf("%d",i+1);
return 0;
}
}
printf("-1");
//printf("%d\n%d\n%d\n",ans1,ans2,ans);
return 0;
}
#include
using namespace std;
#define maxn 100
typedef long long int qq;
qq dp[maxn][maxn];
qq c(int n,int m){
if(n==m||m==0)return 1;
if(dp[n][m]!=-1)return dp[n][m];
return dp[n][m]=c(n-1,m-1)+c(n-1,m);
}
int main(){
memset(dp,-1,sizeof(dp));
int n;
scanf("%d",&n);
for(int i=0;i<n;i++){
for(int j=0;j<=i;j++){
if(j!=0)printf(" ");
printf("%lld",c(i,j));
}
printf("\n");
}
return 0;
}
#include
using namespace std;
#define p3(x) ((x)*(x)*(x))
int f(int x){
int a[10],cnt=0;
int ret=0;
while(x>0){
a[cnt++]=x%10;
ret+=p3(a[cnt-1]);
x/=10;
}
return ret;
}
int main(){
//while(scanf("%d",&n)!=EOF){
for(int i=100;i<1000;i++){
if(f(i)==i)printf("%d\n",i);
}
//}
return 0;
}
#include
using namespace std;
int n;
bool f(int x){
int a[100],cnt=0;
int ret=0;
while(x>0){
a[cnt++]=x%10;
ret+=a[cnt-1];
x/=10;
}
//if(ret!=n)return 0;
for(int i=0;i<cnt/2;i++){
if(a[i]!=a[cnt-1-i])return 0;
}
return 1;
}
int main(){
//while(scanf("%d",&n)!=EOF){
for(int i=1000;i<10000;i++){
if(f(i))printf("%d\n",i);
}
//}
return 0;
}
#include
using namespace std;
int n;
bool f(int x){
int a[100],cnt=0;
int ret=0;
while(x>0){
a[cnt++]=x%10;
ret+=a[cnt-1];
x/=10;
}
if(ret!=n)return 0;
for(int i=0;i<cnt/2;i++){
if(a[i]!=a[cnt-1-i])return 0;
}
return 1;
}
int main(){
while(scanf("%d",&n)!=EOF){
for(int i=10000;i<1000000;i++){
if(f(i))printf("%d\n",i);
}
}
return 0;
}
#include
using namespace std;
const int bas = 16;
char f(int x){
if(x>=10)return x+'A'-10;
else return x+'0';
}
char a[100];
int main(){
long long int n;
scanf("%lld",&n);
if(n==0){
printf("0\n");return 0;
}
int cnt=0;
while(n>0){
a[cnt++]+=f(n%bas);
n/=bas;
}
for(int i=cnt-1;i>=0;i--){
printf("%c",a[i]);
}
return 0;
}
#include
using namespace std;
#define maxn 100052
char a[maxn];
bool c[maxn*4]={0};
int ans[maxn*2];
int f(char x){
if(x>='A'&&x<='F')return x-'A'+10;
else return x-'0';
}
int main(){
int T;
//scanf("%d",&T);
//while(T--){
scanf("%s",a);
int n=strlen(a);
long long int ans=0;
for(int i=0;i<n;i++){
ans<<=4;
ans+=f(a[i]);
}
printf("%lld\n",ans);
//}
return 0;
}
#include
using namespace std;
#define maxn 100052
char a[maxn];
bool c[maxn*4]={0};
int ans[maxn*2];
int f(char x){
if(x>='A'&&x<='F')return x-'A'+10;
else return x-'0';
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%s",a);
int n=strlen(a);
for(int i=n-1,j=0;i>=0;i--,j+=4){
int x=f(a[i]);
c[j]=x&1;
c[j+1]=(x>>1)&1;
c[j+2]=(x>>2)&1;
c[j+3]=(x>>3)&1;
}
int cnt=0;
for(int i=0;i<n*4;i+=3){
ans[cnt++]=(c[i])+ (c[i+1]<<1)+ (c[i+2]<<2);
}
bool flag=0;
for(int i=cnt-1;i>=0;i--){
if(ans[i]!=0)flag=1;
if(flag)printf("%d",ans[i]);
}
printf("\n");
}
return 0;
}
#include
using namespace std;
int a[19000];
int main(){
int n;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
sort(a,a+n);
for(int i=0;i<n;i++){
if(i!=0)printf(" ");
printf("%d",a[i]);
}
return 0;
}
简记:想到一个三分套三分确定坐标的办法,时间复杂度O(n*log(1e10)*log(1e10))的办法,过了60%的数据。
#include
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 100005;
const double eps = 0.01;
struct point{
int x,y;
}a[maxn];
int n;
int x_max=-inf ,x_min=inf ,y_max=-inf, y_min=inf;
double cla(double x, double y){
double ret=0;
for(int i=0;i<n;i++){
double now=min(fabs(a[i].x-a[i].y+y-x), fabs(-a[i].x-a[i].y+x+y));
ret=max(ret, now);
}
return ret;
}
double fy(double x, double l, double r){
double midl,midr,e;
while(r-l>eps){
//printf("ly=%.4lf ry=%.4lf\n",l,r);
e=(r-l)/3;
midl=l+e;
midr=midl+e;
double ansl=cla(x, midl);
double ansr=cla(x, midr);
if(ansl<ansr){
r=midr;
}
else{
l=midl;
}
}
return cla(x, l);
}
double fx(double l, double r){
double midl,midr,e;
while(r-l>eps){
//printf("lx=%.4lf rx=%.4lf\n",l,r);
e=(r-l)/3;
midl=l+e;
midr=midl+e;
double ansl=fy(midl, y_min, y_max);
double ansr=fy(midr, y_min, y_max);
if(ansl<ansr){
r=midr;
}
else{
l=midl;
}
}
return fy(l, y_min, y_max);
}
int main(){
scanf("%d",&n);
double lx,ly,rx,ry;
for(int i=0;i<n;i++){
scanf("%d%d",&a[i].x, &a[i].y);
x_min=min(x_min, a[i].x);
x_max=max(x_max, a[i].x);
y_min=min(y_min, a[i].y);
y_max=max(y_max, a[i].y);
}
//printf("%.4lf %.4lf\n",(double)x_min,(double)x_max);
printf("%.1lf\n",fx(x_min, x_max));
return 0;
}
#include
using namespace std;
const int maxn =100;
int a[maxn],n,m;
bool vis[maxn];
typedef long long int qq;
qq ans;
void dfs(int x, qq s){
if(x==m){
ans=max(ans,s);
return ;
}
for(int i=0;i<n;i++){
if(vis[i])continue;
vis[i]=1;
dfs(x+1, s*a[i]);
vis[i]=0;
}
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
ans=-100000;
memset(vis,0,sizeof(vis));
dfs(0,1);
printf("%lld\n",ans);
}
return 0;
}
#include
using namespace std;
int main(){
int a,b;
while(scanf("%d%d",&a,&b)!=EOF){
printf("%.1lf+%.1lfi\n",a/sqrt(a*a+b*b) , b/sqrt(a*a+b*b));
}
return 0;
}
#include
using namespace std;
typedef long long int qq;
int main(){
qq n;
scanf("%lld",&n);
int a[100]={0},cnt=0;
while(n>0){
a[cnt++]=n%8;
n/=8;
}
for(int i=cnt-1;i>=0;i--){
printf("%d",a[i]);
}
printf("\n");
return 0;
}
#include
using namespace std;
const int maxn = 100;
int main(){
int n,ans=0;
scanf("%d",&n);
for(int i=1;i*i<n;i++){
if(n%i==0)ans+=2;
}
int t=sqrt(n);
if(t*t==n)ans++;
printf("%d\n",ans);
return 0;
}
#include
using namespace std;
const int maxn = 100;
const int inf = 0x3f3f3f3f;
int main(){
int n,ans=-inf,temp=-inf;
while(scanf("%d",&n)!=EOF){
if(n==0){
printf("%d\n",ans);
return 0;
}
if(n>=temp){
ans=temp;
temp=n;
}
else if(n>=ans){
ans=n;
}
}
printf("%d\n",ans);
return 0;
}
#include
using namespace std;
int main(){
long long int a,b;
scanf("%lld%lld",&a,&b);
printf("%lld\n",a*b);
return 0;
}
#include
using namespace std;
int main(){
int n;
scanf("%d",&n);
bool flag=0;
for(int i=2;i*i<=n;i++){
while(n%i==0){
if(flag==1){
printf("*");
}
printf("%d",i);
n/=i;
flag=1;
}
}
if(n!=1){
if(flag==1){
printf("*");
}
printf("%d",n);
}
return 0;
}
简记:动态规划
#include
using namespace std;
#define maxn 1005
typedef long long int qq;
int n;
qq a[maxn],dp[maxn][maxn];
qq f(int l,int r){
if(l==r)return 0;
if(dp[l][r]!=-1)return dp[l][r];
qq ret=-1;
for(int i=l;i<r;i++){
qq x= f(l,i)+ f(i+1,r)+ a[l-1]*a[i]*a[r] ;
if(ret==-1||ret>x) ret=x;
}
return dp[l][r]=ret;
}
qq f2(int n){
memset(dp,-1,sizeof(dp));
for(int i=0;i<=n;i++)dp[i][i]=0;
for(int k=1;k<n;k++){
for(int l=1;l<=n;l++){
if(l+k>n)break;
for(int mid=l;mid<l+k;mid++){
qq x= dp[l][mid]+ dp[mid+1][l+k] + a[l-1]*a[mid]*a[l+k];
if(dp[l][l+k]>x||dp[l][l+k]==-1)
dp[l][l+k]=x;
}
}
}
return dp[1][n];
}
int main(){
memset(dp,-1,sizeof(dp));
scanf("%d",&n);
for(int i=0;i<=n;i++){
scanf("%lld",&a[i]);
}
//qq ans=f(1,n);
qq ans=f2(n);
printf("%lld\n",ans);
return 0;
}
#include
using namespace std;
int lcm(int x,int y){
return x*y/__gcd(x,y);
}
int main(){
int a,b,c;
while(scanf("%d%d%d",&a,&b,&c)!=EOF){
printf("%d\n",lcm(lcm(a,b),c));
}
}
#include
using namespace std;
const int bas = 500;
int a[bas][bas];
int mov[8][2]={{1,0},{-1,0},{0,1},{0,-1},{1,1},{1,-1},{-1,1},{-1,-1}};
bool vis[bas][bas];
void print(int n){
memset(a,-1,sizeof(a));
int mid=n/2;
a[mid][mid]=1;
a[mid+1][mid]=1;a[mid+2][mid]=1;a[mid-1][mid]=1;a[mid-2][mid]=1;
a[mid][mid+1]=1;a[mid][mid+2]=1;a[mid][mid-1]=1;a[mid][mid-2]=1;
for(int i=0;i<100;i++){
memset(vis,0,sizeof(vis));
for(int x=0;x<n;x++)for(int y=0;y<n;y++){
if(a[x][y]!=-1)continue;
int flag=0;
for(int c=0;c<8;c++){
int tx=x+mov[c][0], ty=y+mov[c][1];
if(tx<0||tx>=n||ty<0||ty>=n||a[tx][ty]==-1)continue;
flag=1;
}
if(flag==1){
vis[x][y]=1;
}
}
for(int x=0;x<n;x++)for(int y=0;y<n;y++){
if(vis[x][y]==1){
if(i&1) a[x][y]=1;
else a[x][y]=0;
}
}
}
a[0][n-1]=!(n&1);
a[0][0]=!(n&1);
a[n-1][n-1]=!(n&1);
a[n-1][0]=!(n&1);
}
int main(){
int n;
while(scanf("%d",&n)!=EOF){
print(4*n+5);
for(int i=0;i<4*n+5;i++){
for(int j=0;j<4*n+5;j++){
if(a[i][j]==0)printf(".");
else printf("$");
}
printf("\n");
}
}
return 0;
}
简记:若强行跑O(11!)的时间复杂度再O(11)判断是否可行,会超时,需要在dfs过程中,通过维护已经得到的值来剪枝。
#include
using namespace std;
#define maxn 15
const int bas = 11;
int ans=0, n, a[maxn], vis[maxn];
void print(){
for(int i=0;i<bas;i++){
if(a[i]==0)printf("+");
else if(a[i]==10)printf("/");
else printf("%d",a[i]);
}
printf("\n");
}
int cla(){
int ret=-1;
int flag=0, now=0, mot=0;//是否出现过'/'
for(int i=0;i<bas;i++){
if(a[i]==0){//出现'+'
if(now==0)return -1;
ret=now;
now=0;
}
else if(a[i]==10){//出现'/'
if(now==0)return -1;
mot=now;
now=0;
}
else {
now=now*10+a[i];
}
}
if((mot%now!=0)||(now==0))return -1;
//print();
return ret+mot/now;
}
void dfs(int x, int op, int s, int son, int mot){//0son 1mot 2s
if(x==11){
if(op!=2)return;
if((s==0)||(son%mot!=0))return;
if(s+son/mot==n) ans++;
return ;
}
for(int i=0;i<bas;i++){
int top=op, ts=s, tson=son, tmot=mot;
if(vis[i]==1)continue;
if(i==0){//'+'
if(op!=1||mot==0)continue;
if(son%mot!=0||son/mot>n)continue;
top=2;
}
else if(i==10){//'/'
if(op!=0)continue;
if(son==0)continue;
top=1;
}
else{
if(op==0)tson=son*10+i;
else if(op==1)tmot=mot*10+i;
else ts=s*10+i;
}
vis[i]=1;
//a[x]=i;
dfs(x+1, top, ts, tson, tmot);
vis[i]=0;
}
}
int main(){
while(scanf("%d",&n)!=EOF){
ans=0;
memset(vis,0,sizeof(vis));
dfs(0,0,0,0,0);
printf("%d\n",ans);
}
return 0;
}
简记:一开始理解错了题意,后来百度的其他人方法,发现是一个玄学的dfs+剪枝,最差时间复杂度为:O(2^n*m)。认为没必要费时间练这题~
#include
using namespace std;
int n,m, a[20][20], ans, sum;
int mov[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
bool vis[20][20];
void dfs(int x, int y, int s, int dep){
if(dep>=ans||s>sum)return;
if(s==sum){
/*for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(vis[i][j])printf("%d ",a[i][j]);
else printf("0 ");
}
printf("\n");
}*/
ans=dep;
return;
}
for(int i=0;i<4;i++){
int tx=x+mov[i][0], ty=y+mov[i][1];
if(tx<=0||tx>n||ty<=0||ty>m)continue;
if(vis[tx][ty])continue;
vis[tx][ty]=1;
dfs(tx,ty,s+a[tx][ty],dep+1);
vis[tx][ty]=0;
}
}
int main(){
scanf("%d%d",&m,&n);
ans=n*m;
sum=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%d",&a[i][j]);
sum+=a[i][j];
}
}
if(sum&1){
printf("0\n");
return 0;
}
sum/=2;
memset(vis,0,sizeof(vis));
vis[1][1]=1;
dfs(1,1,a[1][1],1);
if(ans==n*m)printf("0\n");
else printf("%d\n",ans);
return 0;
}
简记:读入有些技巧,如果明白文件输入输出原理的话,会方便不少。
#include
using namespace std;
#define maxn 1000
int a[maxn],num[maxn];
int main(){
int n,x;
scanf("%d",&n);
n=0;
while(scanf("%d",&x)!=EOF){
a[n++]=x;
}
sort(a,a+n);
int ans=-1,ans2=-1;
for(int i=1;i<n;i++){
if(a[i]==a[i-1])ans2=a[i];
if(a[i]!=a[i-1]+1&&a[i]!=a[i-1])ans=a[i]-1;
}
printf("%d %d\n",ans,ans2);
return 0;
}
#include
using namespace std;
#define maxn 1052
char s[maxn];
int a[maxn],b[maxn];
int main(){
int n;
scanf("%s",s);
n=strlen(s);
for(int i=0;i<n;i++){
if(s[i]=='o')a[i]=0;
else a[i]=1;
}
scanf("%s",s);
for(int i=0;i<n;i++){
if(s[i]=='o')b[i]=0;
else b[i]=1;
}
int ans=0;
for(int i=0;i<n-1;i++){
if(a[i]!=b[i]){
ans++;
a[i+1]=!a[i+1];
}
}
if(a[n-1]!=b[n-1])printf("-1\n");//应该是不可能不能成功
else printf("%d\n",ans);
return 0;
}
简记:n方暴力就可以过,没想到巧妙地枚举方法可以做到nlogn。
#include
using namespace std;
const int maxn = 100052;
int a[maxn];
int main(){
int ans,n;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
ans=0;
for(int l=0;l<n;l++){
ans++;
int min0=a[l], max0=a[l];
for(int r=l+1;r<n;r++){
min0=min(min0,a[r]);
max0=max(max0,a[r]);
if(max0-min0==r-l)ans++;
}
}
printf("%d\n",ans);
return 0;
}
/*
题目大意:输入两个数:a,b,找出最大的c满足c不能表示成an+bm(n,m∈N*)
思路:打表找规律
*/
#include
#include
#include
using namespace std;
int dp[1050]={0};
int main()
{
int a,b;
cin>>a>>b;
if(a>b)//a
{
int c=a;
a=b;
b=c;
}
int maxx=0;
for(int i=1;i<b;i++)
{
int x=i;
while(1)
{
if(x%a==0)break;
x+=b;
}
//cout<
if(maxx<x)maxx=x;
}
cout<<maxx-b;
return 0;
}
简记:
1.问题等价于求一棵树的重心
2.实测点数n<=10000,最大路费不超过signed int。
#include
using namespace std;
#define maxn 10052
struct node{
int pos,val;
node(){}
node(int p, int v){
pos=p; val=v;
}
};
int f(int x){
return x*10+(1+x)*x/2;
}
vector<node>u[maxn];
int dis[maxn];
int dfs(int x, int fa, int h){
for(int i=0;i<u[x].size();i++){
if(u[x][i].pos==fa)continue;
dfs(u[x][i].pos, x, h+u[x][i].val);
}
return dis[x]=h;
}
int main(){
int n;
scanf("%d",&n);
for(int i=0;i<n-1;i++){
int s,t,w;
scanf("%d%d%d",&s,&t,&w);
u[s].push_back(node(t,w));
u[t].push_back(node(s,w));
}
dfs(1, -1, 0);
int root=0;
for(int i=1;i<=n;i++){
if(root==0||dis[i]>dis[root])root=i;
}
//printf("root=%d\n",root);
dfs(root, -1, 0);
int ans=0;
for(int i=1;i<=n;i++){
if(ans==0||dis[i]>dis[ans])ans=i;
}
//printf("ans=%d\n",ans);
printf("%d\n",f(dis[ans]));
return 0;
}
简记:
1.一般这种求区间[L,R]之间个数的,变成求[1,R]个数-[1,L-1]个数。
2.乍一看,平均下来每次压缩是个logn级别的操作,权当一试。
3.1e6超时,5e5优化到了极致,可以通过数据,但是应该还是有问题,我觉得是题目问题。
#include
using namespace std;
#define maxn 500052
int a[maxn];
int f(int x, int len){//将a数组中下标为x的倍数的位置的数字删除,返回数组长度
if(x>len)return len;
int cnt=x;
for(int i=x;i<=len;i++){
if(i%x==0)continue;
a[cnt++]=a[i];
}
a[cnt]=0;
return cnt-1;
}
int init(){
int ret=1;
int len=maxn/2;
for(int i=1;i<=len;i++){
a[i]=i*2-1;
}
ret++;
while(a[ret]!=0){
if(a[ret]>len)break;
/*printf("ans[%d]=%d ",ret,a[ret]);
for(int i=1;i<=len;i++){
printf("%d ",a[i]);
}
printf("\n");*/
len=f(a[ret], len);
ret++;
}
return ret;
}
int main(){
init();
int n,m;
scanf("%d%d",&n,&m);
int ans=0,flag=0;
for(int i=0;a[i]<m;i++){
if(a[i]>n)flag=1;
if(flag==1)ans++;
}
printf("%d\n",ans);
}
简记:
这次练一下指针形式建树。这个横向输出实在麻烦,预声明了二维字符数组,递归画出,最后输出。
#include
using namespace std;
#define maxn 1052
struct node{
int data,size;
node *l, *r;
};
node *build_node(int data){
node *ret=new node;
ret->data=data;
ret->l=NULL;
ret->r=NULL;
ret->size=1;
}
struct sort_tree{
int pos[10052];//pos[x]表示x为第pos[x]大
node *root=new node;
bool empty=1;
int size=0, cnt;
char mp[105][1000];
void draw(node *o, int y, bool flag){//第y列加入o
int now=o->data, x=pos[o->data], ty=y, k=0;
char p[10]={0};
while(now>0){
p[k++]=now%10+'0';
now/=10;
}
if(flag==0){
mp[x][ty++]='-';
}
for(int i=k-1;i>=0;i--,ty++){//画数字
mp[x][ty]=p[i];
}
if(o->l!=NULL||o->r!=NULL){//画后缀“-|”
mp[x][ty++]='-';
mp[x][ty]='|';
}
if(o->l!=NULL)//向下画‘|’
for(int i=x;i<=pos[o->l->data];i++){
mp[i][ty]='|';
}
if(o->r!=NULL)//向上画‘|’
for(int i=pos[o->r->data];i<=x;i++){
mp[i][ty]='|';
}
if(o->l!=NULL||o->r!=NULL)ty++;
mp[x][ty]='\0';
if(o->r!=NULL){//画右子树
draw(o->r, ty, 0);
}
if(o->l!=NULL){//画左子树
draw(o->l, ty, 0);
}
}
void out(){
for(int i=0;i<=size;i++){
for(int j=0;j<1000;j++){
mp[i][j]='.';
}
}
draw(root, 0, 1);
for(int i=1;i<=size;i++){
printf("%s\n",mp[i]);
}
}
void print(node *x){
if(x->r!=NULL){
print(x->r);
}
//printf("%d ",x->data);
pos[x->data]=cnt++;
if(x->l!=NULL){
print(x->l);
}
}
void print(){
memset(pos,-1,sizeof(pos));
cnt=1;
print(root);
}
void add(node *x, int v){
x->size++;
if(x->data >v){
if(x->l==NULL) x->l= build_node(v);
else add(x->l, v);
}
else {
if(x->r==NULL) x->r= build_node(v);
else add(x->r, v);
}
}
void add(int v){
size++;
if(empty){
root->data=v;
root->l=NULL;
root->r=NULL;
root->size=1;
empty=0;
}
else add(root, v);
}
};
int main()
{
//freopen("in.txt","r",stdin);
sort_tree x;
int n;
while(scanf("%d",&n)!=EOF){
x.add(n);
}
x.print();
x.out();
return 0;
}
简记:
依次在图中删除每一个点,判断s到t是否依然连通,时间复杂度O(n*m)。直觉感觉应该是还有更快的办法,没认真想。
#include
using namespace std;
const int maxn = 1005;
const int maxm = 2005;
struct Graph{
vector<int>a[maxn];
bool vis[maxn];
int n,m;
void input(){
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++){
int ss,tt;
scanf("%d%d",&ss,&tt);
a[ss].push_back(tt);
a[tt].push_back(ss);
}
}
void dfs(int x, int del){
vis[x]=1;
for(int i=0;i<a[x].size();i++){
if(a[x][i]==del|| vis[a[x][i]]) continue;
dfs(a[x][i], del);
}
}
int cla(int s, int t){
int ret=0;
for(int i=1;i<=n;i++){
if(i==s||i==t)continue;
memset(vis,0,sizeof(vis));
dfs(s, i);
if(vis[t]==0)ret++;
}
return ret;
}
};
int main(){
Graph ans;
ans.input();
int s,t;
scanf("%d%d",&s,&t);
printf("%d\n",ans.cla(s,t));
return 0;
}
简记:
枚举每条边(u,v),以这条边为中间边的合法边数为:(和u相连的点数-1)*(和v相连的点数-1)
#include
using namespace std;
typedef long long int qq;
const int node_size = 10005;
const int edge_size = 100005;
struct Graph{
vector<int>u[node_size];
int n,m;
void clear(){
for(int i=0;i<node_size;i++){
u[i].clear();
}
}
void add_edge(int s, int t){
u[s].push_back(t);
u[t].push_back(s);
}
void input(){
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++){
int ss,tt;
scanf("%d%d",&ss,&tt);
add_edge(ss,tt);
}
}
qq cla(){
qq ret=0;
for(int i=1;i<=n;i++){
for(int j=0;j<u[i].size();j++){
ret+=(u[i].size()-1)*(u[u[i][j]].size()-1);
}
}
return ret;
}
};
int main(){
Graph ans;
ans.clear();
ans.input();
printf("%lld\n",ans.cla());
return 0;
}
简记:
首先两两组合看成nim博奕问题,奇数个就在最高点加一个。但是目标是一定要优先移动最左边的。有个坑点,对于一对点,可以变大也可以变小。
#include
using namespace std;
const int maxn = 10005;
int a[maxn],c[maxn],n;
int main(){
n=0;
while(scanf("%d",&a[n])!=EOF){
n++;
}
if(n&1){
a[n]=a[n-1]+1;
n++;
}
int ans=0;
for(int i=0,j=0;i<n;j++,i+=2){
c[j]=a[i+1]-a[i]-1;
ans^=c[j];
}
//printf("ans=%d\n",ans);
if(ans==0){
printf("-1\n");
}
else{
int m=n/2;
for(int i=0;i<m;i++){
int t=ans^c[i];
if(t<c[i]){
printf("%d %d",a[i*2],a[i*2]+c[i]-t);
break;
}
else if(i*2+2<n&& a[i*2]+t+1<a[i*2+2]){
printf("%d %d",a[i*2+1],a[i*2]+t+1);
break;
}
}
}
return 0;
}
简记:动态规划
#include
using namespace std;
typedef long long qq;
const qq mod = 1000000007;
const int maxn = 1005;
qq a[maxn];
qq b[maxn];//不能直接使用公式,会超出范围
int main()
{
int n;
scanf("%d",&n);
if(n==1)
{
printf("2\n");
return 0;
}
memset(a,0,sizeof(a));
b[1]=1;
for(int i=2;i<=n;i++)
{
b[i]=b[i-1]*2%mod;
}
a[1]=1;a[2]=6;
for(int i=3;i<=n;i++)
{
a[i]=a[i-2]*4+a[i-1]*2+b[i];
a[i]%=mod;
}
qq sum=0;
for(int i=2;i<n;i++)
{
sum+=(b[n-i+1]*a[i-1] + b[i]*a[n-i]) *4;
sum%=mod;
}
sum+=a[n]*4;
sum%=mod;
printf("%lld\n", sum);
return 0;
}
简记:记好状态BFS即可
#include
using namespace std;
const int bas = 3;
const int mov[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
map<int,bool>vis;
struct state{
int a[bas][bas];
int hast, posx, posy, step;
int hash(){
int ret=0;
for(int x=0;x<bas;x++)
for(int y=0;y<bas;y++){
ret=ret*10+a[x][y];
}
return ret;
}
state f(int op){
state ret= *this;
int tx=posx+mov[op][0], ty=posy+mov[op][1];
if(tx<0||tx>=bas||ty<0||ty>=bas){
ret.hast=-1;
return ret;
}
swap(ret.a[posx][posy], ret.a[tx][ty]);
ret.posx=tx, ret.posy=ty;
ret.step++;
ret.hast=ret.hash();
return ret;
}
void input(){
char temp[15];
scanf("%s",temp);
for(int i=0;i<9;i++){
if(temp[i]=='.') {
this->posx=i/3, this->posy=i%3;
this->a[i/3][i%3]=0;
}
else this->a[i/3][i%3]=temp[i]-'0';
}
this->step=0;
this->hast=this->hash();
}
void out(){
printf("hast=%d\n",this->hast);
for(int i=0;i<bas;i++){
for(int j=0;j<bas;j++){
printf("%d ",a[i][j]);
}
printf("\n");
}
printf("\n");
}
};
int bfs(state s, state t){
queue<state>q;
q.push(s);
vis[s.hast]=1;
while(!q.empty()){
state now=q.front();
//now.out();
q.pop();
for(int i=0;i<4;i++){
state x=now.f(i);
if(x.hast==-1||vis.count(x.hast)!=0){
continue;
}
if(x.hast==t.hast)return x.step;
vis[x.hast]=1;
q.push(x);
}
}
return -1;
}
int main(){
state s,t;
s.input();
t.input();
cout<<bfs(s,t)<<endl;
return 0;
}
#include
using namespace std;
int n;
bool f(int x){
int a[100],cnt=0;
int ret=0;
while(x>0){
a[cnt++]=x%10;
ret+=a[cnt-1];
x/=10;
}
if(ret!=n)return 0;
for(int i=0;i<cnt/2;i++){
if(a[i]!=a[cnt-1-i])return 0;
}
return 1;
}
int main(){
while(scanf("%d",&n)!=EOF){
int flag=0;
for(int i=10000;i<1000000;i++){
if(f(i)){
flag=1;
printf("%d\n",i);
}
}
if(flag==0){
printf("-1\n");
}
}
return 0;
}
简记:经典的并查集问题,首先把边根据失去的时间点排序,返向连接,如果连接边ab的时候,发现连接前ab之间不可达,那么这一天就会有人抗议。
#include
using namespace std;
const int maxn = 100052;
bool vis[maxn];
struct Edge{
int v1,v2,t;
}v[maxn];
bool operator <(Edge a, Edge b){
return a.t > b.t;
}
struct tree_set{
int fa[maxn/10],size;
void init(int x){
size=x;
for(int i=1;i<=x;i++){
fa[i]=i;
}
}
int f(int x){
if(fa[x]!=x) return fa[x]=f(fa[x]);
else return fa[x];
}
bool Is_connect(int x, int y){//x,y是否已经相连
if(f(x)==f(y))return 1;
else return 0;
}
bool merge(int x, int y){//x,y两点合并
if(Is_connect(x,y) )return 0;//连接失败,本来就相连
fa[f(x)]=f(y);
return 1;
}
};
int main(){
memset(vis,0,sizeof(vis));
int n,m;
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++){
scanf("%d%d%d",&v[i].v1, &v[i].v2, &v[i].t);
}
sort(v,v+m);
tree_set x;
x.init(n);
int ans=0;
for(int i=0;i<m;i++){
if(x.Is_connect(v[i].v1, v[i].v2))continue;
else {
x.merge(v[i].v1, v[i].v2);
if(!vis[v[i].t])ans++;
vis[v[i].t]=1;
}
}
printf("%d\n",ans);
return 0;
}
简记:
当前n个人围成一个环,第一个人从1开始报数,顺次每个人说的的数字加1。现在计算第一个人前t次所报数目的总和为多少。(报数过程在模k的完全剩余系中进行),显然:f(n)= n*(n-1)/2+1
注:取模小小小技巧,小心坑点
#include
using namespace std;
typedef long long int qq;
qq f(qq x,qq k){
if(x&1){
return ((((x-1)/2)%k)*(x%k)+1)%k;
}
else return (((x/2)%k)*((x-1)%k)+1)%k;
}
int main(){
qq n,k,t;
scanf("%lld%lld%lld",&n,&k,&t);
qq ans=0,x=1;
for(int i=1;i<=t;i++,x=x+n){
ans+=f(x,k);
}
printf("%lld\n",ans);
return 0;
}
简记:
显然的最小生成树问题,对于河流,就看成是一个节点,每个点建码头就是向该点连一条边。
注意有坑点:
1.分别跑一次没有河流的n个点的最小生成树和一次有河流的n+1个点的最小生成树
2.边权小于0的边一定要选,只赚不亏。所以只能用kruskal
#include
using namespace std;
const int node_size = 10005;
const int edge_size = 100005;
const int inf = 0x3f3f3f3f;
struct edge{
int s,t,w;
edge(){};
edge(int ss, int tt, int ww){
s=ss; t=tt; w=ww;
}
};
bool operator < (edge l, edge r){
return l.w< r.w;
}
struct tree_set{
int fa[node_size],size;
void init(int x){
size=x;
for(int i=1;i<=x;i++){
fa[i]=i;
}
}
int f(int x){
if(fa[x]!=x) return fa[x]=f(fa[x]);
else return fa[x];
}
bool Is_connect(int x, int y){//x,y是否已经相连
if(f(x)==f(y))return 1;
else return 0;
}
bool merge(int x, int y){//x,y两点合并
if(Is_connect(x,y) )return 0;//连接失败,本来就相连
fa[f(x)]=f(y);
return 1;
}
};
struct Graph{
vector<edge>u[node_size];
vector<edge>a;
int n,m;//点数
void add_edge(edge x){
u[x.s].push_back(x);
int temp=x.s; x.s=x.t; x.t=temp;
u[x.s].push_back(x);
a.push_back(x);
}
void clear(){
n=0,m=0;
for(int i=0;i<node_size;i++){
u[i].clear();
}
a.clear();
}
void input(){
clear();
scanf("%d%d",&n,&m);
int mm=m;
while(mm--){
int ss,tt,ww;
scanf("%d%d%d",&ss,&tt,&ww);
add_edge( edge(ss,tt,ww) );
}
}
bool vis[node_size];
int prim(){//求最小生成树,如果不存在就返回inf
memset(vis,0,sizeof(vis));
int ret=0,k=1;
priority_queue<edge>p;
for(int i=0;i<u[1].size();i++){
p.push(u[1][i]);
}
vis[1]=1;
while(k<n){
if(p.empty())return inf;
edge now= p.top();
while(vis[now.t]){
p.pop();
if(p.empty())return inf;
now= p.top();
}
if(vis[now.t]) return inf;//不连通
vis[now.t]=1;
ret+=now.w;
k++;
for(int i=0;i<u[now.t].size();i++){
p.push(u[now.t][i]);
}
}
return ret;
}
bool cmp_kruskal(edge a, edge b){
return a.w< b.w;
}
int kruskal(){
int ret=0,k=0;
sort(a.begin(),a.end());
tree_set p;
p.init(n);
for(int i=0;i<a.size();i++){
if(a[i].w<0){
ret+=a[i].w;
k+=p.merge(a[i].s,a[i].t);
continue;
}
if(!p.Is_connect(a[i].s, a[i].t)){
ret+=a[i].w;
k+=p.merge(a[i].s, a[i].t);
}
if(k==n-1)return ret;
}
if(k==n-1) return ret;
else return inf;
}
};
int main(){
Graph ans;
int x=inf;
ans.input();
x=ans.kruskal();
//printf("x=%d\n",x);
for(int i=1;i<=ans.n;i++){
int temp=0;
scanf("%d",&temp);
if(temp==-1)continue;
ans.add_edge( edge(i,ans.n+1,temp));
ans.add_edge( edge(ans.n+1,i,temp));
}
ans.n++;
printf("%d\n",min(x, ans.kruskal()) );
return 0;
}
简记:算是挺经典的问题了,算一个500500的矩阵的最大子矩阵,相当于枚举使用哪些行O(nn),对每次枚举,求最大子段和O(m)
#include
using namespace std;
#define maxn 505
#define inf 0x3f3f3f3f
int sum[maxn][maxn];
int main(){
int n,m,x;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%d",&x);
sum[i][j]=sum[i-1][j]+x;
}
}
int ans=-inf;
for(int l=1;l<=n;l++){
for(int r=l;r<=n;r++){
int dp=0;
for(int i=1;i<=m;i++){
int t=sum[r][i]-sum[l-1][i];
if(dp>0)dp+=t;
else dp=t;
if(dp>ans)ans=dp;
}
}
}
printf("%d\n",ans);
return 0;
}
简记:分类讨论,挺麻烦的,一定要谨慎。
#include
using namespace std;
const int maxn = 150;
int n;
struct point{
int x,dir;
}a[maxn],s;
bool operator < (point x, point y){
return x.x< y.x;
}
int main(){
scanf("%d",&n);
for(int i=0;i<n;i++){
int x;
scanf("%d",&x);
a[i].dir=x/abs(x);
a[i].x=abs(x);
}
s=a[0];
sort(a,a+n);
int ans=0;
/*for(int i=0;i
if(s.dir==1){//向右
int pos=-1, c; bool flag=0;
for(int i=0;i<n;i++){
if(a[i].x==s.x&&a[i].dir==s.dir){
pos=i;break;
}
}
for(int i=pos+1;i<n;i++){
if(a[i].dir*s.dir==-1){
ans++;
if(flag==0){
c=i;
flag=1;
}
}
}
if(flag==1){
for(int i=c-1;i>=0;i--){
if(a[i].dir==s.dir&&a[i].x==s.x)continue;
if(a[i].dir*a[c].dir==-1)ans++;
}
}
}
else{
int pos=-1, c; bool flag=0;
for(int i=0;i<n;i++){
if(a[i].x==s.x&&a[i].dir==s.dir){
pos=i;break;
}
}
for(int i=pos-1;i>=0;i--){
if(a[i].dir*s.dir==-1){
ans++;
if(flag==0){
c=i;
flag=1;
}
}
}
//printf("ans=%d\n",ans);
if(flag==1){
for(int i=c+1;i<n;i++){
if(a[i].dir==s.dir&&a[i].x==s.x)continue;
if(a[i].dir*a[c].dir==-1)ans++;
}
}
}
printf("%d\n",ans+1);
return 0;
}
简记:
1.状态设定: d p ( i , j , k , h ) dp(i,j,k,h) dp(i,j,k,h)表示在点 ( i , j ) (i,j) (i,j),当前手里有 k k k个物品,最大的为 h h h的路径数。
2.状态转移方程:
d p ( i , j , k , h ) = 选 c ( i , j ) + 不 选 c ( i , j ) ; dp(i,j,k,h)=选c(i,j) +不选c(i,j); dp(i,j,k,h)=选c(i,j)+不选c(i,j);
选 c ( i , j ) : d p ( i − 1 , j , k − 1 , [ 0 , h − 1 ] ) + d p ( i , j − 1 , k − 1 , [ 0 , h − 1 ] ) 前 提 h = = c ( i , j ) & & k ! = 0 选c(i,j):dp(i-1,j,k-1,[0,h-1])+dp(i,j-1,k-1,[0,h-1]) 前提 h==c(i,j) \&\& k!=0 选c(i,j):dp(i−1,j,k−1,[0,h−1])+dp(i,j−1,k−1,[0,h−1])前提h==c(i,j)&&k!=0
不 选 c ( i , j ) : d p ( i − 1 , j , k , h ) + d p ( i , j − 1 , k , h ) ; 不选c(i,j):dp(i-1,j,k,h)+dp(i,j-1,k,h); 不选c(i,j):dp(i−1,j,k,h)+dp(i,j−1,k,h);
3.初始状态:
d p ( 0 , 0 , 0 , 0 ) = 1 ; dp(0,0,0,0)=1; dp(0,0,0,0)=1;
d p ( 0 , 0 , 1 , c ( 0 , 0 ) ) = 1 ; dp(0,0,1,c(0,0))=1; dp(0,0,1,c(0,0))=1;
一个坑点:有的礼物价值会为 0 0 0,转移过程会出问题,解决办法: c [ i ] [ j ] + + ; c[i][j]++; c[i][j]++;
#include
using namespace std;
#define MOD 1000000007
#define mod(x) ((x)%MOD)
const int bas = 55;
const int maxn = 15;
typedef long long int qq;
qq dp[bas][bas][bas][maxn];
int n,m,p,c[bas][bas],w;
int main(){
while(scanf("%d%d%d",&n,&m,&p)!=EOF){
w=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%d",&c[i][j]);
c[i][j]++;
w=max(w,c[i][j]);
}
}
memset(dp,0,sizeof(dp));
dp[1][1][0][0]=1;
dp[1][1][1][c[1][1]]=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(i==1&&j==1)continue;
for(int k=0;k<=p;k++){
for(int h=0;h<=w;h++){
dp[i][j][k][h]=0;
if(c[i][j]==h&&k!=0){//选c[i][j]
for(int u=0;u<h;u++){
dp[i][j][k][h]+=dp[i-1][j][k-1][u]+dp[i][j-1][k-1][u];
}
}
dp[i][j][k][h]=mod(dp[i][j][k][h]+ dp[i-1][j][k][h]+ dp[i][j-1][k][h]);
}}}}
qq ans=0;
for(int i=0;i<=w;i++){
ans+=dp[n][m][p][i];
}
printf("%lld\n",mod(ans));
}
return 0;
}
简记:
数论类技巧公式,可以打表找规律
g ( x ) = ∑ i = 1 x f ( i ) = f ( n + 2 ) − 1 ; g(x)=\sum_{i=1}^{x}f(i)=f(n+2)-1; g(x)=∑i=1xf(i)=f(n+2)−1;
f ( n ) % f ( m ) = f ( n % m ) ∗ f ( m − 1 ) ⌊ n m ⌋ ; f(n)\%f(m)=f(n\%m)*f(m-1)^{\lfloor\frac nm\rfloor}; f(n)%f(m)=f(n%m)∗f(m−1)⌊mn⌋;
样例没过,但是满分了,最后一点很复杂的分类讨论不想看了~
#include
using namespace std;
typedef long long int qq;
#define mod(x,P) ((x)%P)
#define moc(x,P) (((x)>=P)?((x)-(P)):(x))
struct Mat{
qq a[2][2];
}o,e,u;
qq n,m,p;
qq fast_mul(qq x, qq y, qq p){
qq ret=0;
x=mod(x,p);
y=mod(y,p);
while(x>0){
if(x&1)ret=moc(ret+y,p);
x>>=1;
y=moc(y<<1,p);
}
return ret;
}
qq fast_pow(qq x, qq k, qq p){
qq ret=1;
x=mod(x,p);
while(k>0){
if(k&1)ret=fast_mul(ret,x,p);
k>>=1;
x=fast_pow(x,x,p);
}
return moc(ret,p);
}
Mat operator * (Mat x, Mat y){
Mat ret=o;
for(int i=0;i<2;i++){
for(int j=0;j<2;j++){
for(int k=0;k<2;k++){
ret.a[i][j]=moc(ret.a[i][j]+fast_mul(x.a[i][k],y.a[k][j],p), p);
}}}
return ret;
}
Mat operator ^ (Mat x, qq k){
Mat ret=e;
while(k>0){
if(k&1)ret=ret*x;
k>>=1;
x=x*x;
}
return ret;
}
void init(){
e.a[0][0]=1; e.a[0][1]=0; e.a[1][0]=0; e.a[1][1]=1;
o.a[0][0]=0; o.a[0][1]=0; o.a[1][0]=0; o.a[1][1]=0;
u.a[0][0]=1; u.a[0][1]=1; u.a[1][0]=1; u.a[1][1]=0;
}
qq f(qq x){
Mat ret;
ret=u^(x-1);
return ret.a[0][0];
}
qq real(qq n, qq m)
{
qq a=n%m;
if(a%2) return f(m-a);
return((f(m)-f(m-a))%p+p)%p;
}
qq solve(qq n, qq m)
{
qq t1=n/m;
if(m%2)
{
if(!t1%2&&!t1%4) return f(n%m);
if(!t1%2&&t1%4) return ((f(m)-f(n%m))%p+p)%p;
if(t1%2&&!t1%4) return real(n,m);
if(t1%2&&t1%4) return ((f(m)-real(n,m))%p+p)%p;
}
else
{
if(t1%2) return real(n,m);
else return f(n%m);
}
}
qq get_value(qq n, qq m)
{
n+=2;
qq a=solve(n,m);
if(!a) return f(m)-1;
else return a-1;
}
int main(){
init();
while(scanf("%lld%lld%lld",&n,&m,&p)!=EOF){
qq ans=get_value(n,m);
printf("%lld\n",ans);
}
return 0;
}
简记:简单dp,时间复杂度O(n*n)
#include
typedef long long LL;
using namespace std;
const int MOD = 1e8+7;
LL dp[1005][1005], tmp1, tmp2;
int main()
{
LL n, s, a, b;
cin>>n>>s>>a>>b;
dp[1][(s%n+n)%n] = 1;
for (int i = 1; i < n; i++)
{
tmp1 = b*(n-i)%n;
tmp2 = a*(n-i)%n;
for (int j = 0; j < n; j++)
{
dp[i+1][(j+tmp1)%n] = (dp[i+1][(j+tmp1)%n] + dp[i][j]) % MOD;
dp[i+1][(j-tmp2+n)%n] = (dp[i+1][(j-tmp2+n)%n] + dp[i][j]) % MOD;
}
}
cout<<dp[n][0]<<endl;
return 0;
}
简记:树状数组维护
设:
f(i)=a[i]左边严格大于a[i]的元素个数。
g(i)=a[i]右边严格小于a[i]的元素个数。
则:
a[i]的不高兴度为:1+2+…+f(i) + 1+2+…+g(i);
#include
using namespace std;
const int maxn = 100052;
typedef long long int qq;
int n;
struct Data{
int val,id;
}a[maxn];
int p[maxn],c[maxn];
qq f(qq x){
return (x+1)*x/2;
}
bool operator < (Data x, Data y){
return x.val<y.val;
}
bool cmp_id(Data x, Data y){
return x.id<y.id;
}
struct Bit_tree{
int a[maxn],size;
int lowbit(int x){
return x&(-x);
}
void init(int x){
size=x;
for(int i=0;i<=size;i++){
a[i]=0;
}
}
void push(int pos, int val){
while(pos<=size){
a[pos]+=val;
pos+=lowbit(pos);
}
}
int ask(int pos){
int ret=0;
while(pos>0){
ret+=a[pos];
pos-=lowbit(pos);
}
return ret;
}
int ask(int l,int r){
if(l>r)return 0;
return ask(r)-ask(l-1);
}
};
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i].val);
a[i].id=i;
}
///离散化
sort(a+1,a+1+n);
int now=0;
for(int i=1;i<=n;i++){
if(i==1||a[i].val>a[i-1].val)now++;
c[i]=now;
}
for(int i=1;i<=n;i++){
a[i].val=c[i];
}
///树状数组统计 p
sort(a+1,a+1+n,cmp_id);
memset(p,0,sizeof(p));
Bit_tree tr;
tr.init(now);
for(int i=1;i<=n;i++){//a[i]左边比a[i]大的元素
p[i]+=tr.ask(a[i].val+1,now);
tr.push(a[i].val, 1);
}
tr.init(now);
for(int i=n;i>0;i--){//a[i]右边比a[i]小的元素
p[i]+=tr.ask(1,a[i].val-1);
tr.push(a[i].val, 1);
}
qq ans=0;
for(int i=1;i<=n;i++){
ans+=f(p[i]);
}
printf("%lld\n",ans);
return 0;
}
#include
#include
#include
using namespace std;
int a[1100]={0};
int n;
int num=0;
bool is_same()
{
for(int i=0;i<n;i++)
{
if(a[0]!=a[i])return 0;
}
return 1;
}
void change()
{
int b[1100]={0};
for(int i=0;i<n;i++)
{
a[i]=a[i]/2;
b[i+1]=a[i];
}
a[0]=a[0]+b[n];
for(int i=1;i<n;i++)
{
a[i]=a[i]+b[i];
}
}
void add()
{
for(int i=0;i<n;i++)
{
if(a[i]%2==1)
{
num++;
a[i]++;
}
}
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)
{
cin>>a[i];
}
while(1)
{
if(is_same())break;
change();
add();
}
cout<<num;
return 0;
}
//简单模拟
#include
#include
#include
using namespace std;
int l[5]={0,4,1,2,3};//左转数组
int r[5]={0,2,3,4,1};//右转数组
int movex[5]={0,0,1,0,-1};
int movey[5]={0,-1,0,1,0};
bool color[150][150]={0};
int x,y;//起始坐标(x,y)
int f;
void move()//在点(x,y)朝向f
{
if(color[y][x]==1)//如果是黑砖,右转90度,将该格改为白格,并向前移一格;
{
f=r[f];
color[y][x]=0;
x=x+movex[f];
y=y+movey[f];
}
else//若蚂蚁在白格,左转90度,将该格改为黑格,并向前移一格。
{
f=l[f];
color[y][x]=1;
x=x+movex[f];
y=y+movey[f];
}
}
int main()
{
int m,n;
cin>>m>>n;//m行n列
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
scanf("%d",&color[i][j]);
}
}
int k;char s;//上下左右分别用:U1,D3,L4,R2
cin>>y>>x;
scanf(" %c",&s);
if(s=='U')f=1;
if(s=='R')f=2;
if(s=='D')f=3;
if(s=='L')f=4;
cin>>k;
/*if(k==0)
{
cout<
for(int i=0;i<k;i++)
{
move();
}
cout<<y<<" "<<x;
return 0;
}
简记:
思路:m*n的方格,ans = sqrt(m)*sqrt(n); 向下取整floor。大数据,二分求根号。
注:模拟十进制只能90分,压万进制可以满分
#include
using namespace std;
const int maxn = 2005;
const int bit = 10000;
struct Bnum{
int a[maxn/4], len;
void input(){
memset(a,0,sizeof(a));
char temp[maxn/2];
scanf("%s",temp);
len=strlen(temp);
for(int i=0,j=len-1; j>=0; i++,j-=4){
a[i]+=(temp[j]-'0');
if(j-1>=0) a[i]+=(temp[j-1]-'0')*10;
if(j-2>=0) a[i]+=(temp[j-2]-'0')*100;
if(j-3>=0) a[i]+=(temp[j-3]-'0')*1000;
}
len=(len-1)/4+1;
}
void print(){
for(int i=len-1;i>=0;i--){
if(i==len-1)printf("%d",a[i]);
else printf("%04d",a[i]);
}
printf("\n");
}
}e,o;
void init(){
memset(e.a,0,sizeof(e.a));
e.len=1; e.a[0]=1;
memset(o.a,0,sizeof(o.a));
o.len=1;
}
bool operator <= (Bnum x, Bnum y){
if(x.len!=y.len) return x.len<y.len;
int pos=x.len-1;
while(pos>=0){
if(x.a[pos]==y.a[pos]){
pos--;continue;
}
return x.a[pos]<=y.a[pos];
}
return 1;
}
Bnum operator + (Bnum x, Bnum y){
Bnum ret=o;
ret.len=max(x.len, y.len);
for(int i=0;i<ret.len;i++){
ret.a[i]=x.a[i]+y.a[i];
}
for(int i=0;i<ret.len;i++){
ret.a[i+1]+=ret.a[i]/bit;
ret.a[i]%=bit;
}
if(ret.a[ret.len]!=0) ret.len++;
return ret;
}
Bnum operator + (Bnum x, int y){//+1
Bnum ret=x;
ret.a[0]+=y;
int p=0;
for(int i=0;i<ret.len;i++){
if(ret.a[i]/bit==0) break;
ret.a[i+1]+=ret.a[i]/bit;
ret.a[i]%=bit;
}
if(ret.a[ret.len]!=0)ret.len++;
return ret;
}
Bnum operator - (Bnum x, int y){//-1
Bnum ret=x;
ret.a[0]-=y;
for(int i=0;i<ret.len;i++){
if(ret.a[i]>=0) break;
ret.a[i+1]--;
ret.a[i]+=bit;
}
if(ret.a[ret.len-1]==0)ret.len--;
if(ret.len==0)ret.len++;
return ret;
}
Bnum operator * (Bnum x, Bnum y){
Bnum ret=o;
for(int i=0;i<x.len;i++){
for(int j=0;j<y.len;j++){
ret.a[i+j]+=x.a[i]*y.a[j];
}
}
ret.len=x.len+y.len-1;
for(int i=0;i<ret.len;i++){
ret.a[i+1]+=ret.a[i]/bit;
ret.a[i]%=bit;
}
if(ret.a[ret.len]!=0) ret.len++;
return ret;
}
Bnum operator / (Bnum x, int k){//除2下取整
Bnum ret=x;
for(int i=ret.len-1;i>=0;i--){
if(i!=0) ret.a[i-1]+=bit*(ret.a[i]&1);
ret.a[i]>>=1;
}
if(ret.a[ret.len-1]==0)ret.len--;
return ret;
}
Bnum sqrt(Bnum x){
Bnum l=e, r=x, mid;
while(l<=r){
mid=(l+r)/2;
//printf("l="); l.print();
//printf("r="); r.print();
//printf("mid="); mid.print();
if((mid*mid)<=x)l=mid+1;
else r=mid-1;
}
return l-1;
}
void test(){
Bnum x;
long long int y;
x.input();
x.print();
scanf("%lld",&y);
printf("%lld\n",(long long int)sqrt(y));
x=sqrt(x);
x.print();
x=x*x;
x.print();
}
int main(){
init();
//while(1)test();
Bnum x,y;
x.input();
y.input();
Bnum ans=sqrt(x)*sqrt(y);
ans.print();
return 0;
}
简记:
对于解决带括号的表达式求解问题,递归比较方便。
#include
using namespace std;
const int maxn = 105;
char s[maxn];
int f(int &l, int r){
int ret=0;
while(l<r){
//printf("%d %c %d\n",l,s[l],ret);
if(s[l]=='x'){
l++;ret++;
}
if(s[l]=='('){
l++;
ret+=f(l, r);
}
if(s[l]=='|'){
l++;
return max(ret, f(l, r));
}
if(s[l]==')'){
l++;
return ret;
}
}
return ret;
}
int main(){
scanf("%s",s);
int x=0;
printf("%d\n",f(x,strlen(s)));
return 0;
}
简记:数论常识+打表找规律
#include
using namespace std;
const int maxn = 105;
int a[maxn],n;
bool vis[maxn*maxn];
int main(){
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
int gcd=a[0];
for(int i=1;i<n;i++){
gcd=__gcd(gcd,a[i]);
}
if(gcd!=1){
printf("INF\n");
}
else{
vis[0]=1;
int ans=0;
for(int i=0;i<n;i++){
for(int j=0;j<maxn*maxn;j++){
if(j-a[i]>=0){
vis[j]=max( vis[j], vis[j-a[i]] );
}
}
}
bool first=1;
for(int i=0;i<maxn*maxn;i++){
if(!vis[i]){
ans++;
}
}
printf("%d\n",ans);
}
return 0;
}
简记:整体二分答案
#include
using namespace std;
const int maxn = 100005;
typedef long long int qq;
struct choc{
qq h,w;
}a[maxn];
int n;
qq k;
qq f(int x, choc p){
return (p.h/x)*(p.w/x);
}
bool is_ok(int x){
qq ans=0;
for(int i=0;i<n;i++){
ans+=f(x,a[i]);
}
return ans>=k;
}
int main(){
scanf("%d%lld",&n,&k);
for(int i=0;i<n;i++){
scanf("%lld%lld",&a[i].w,&a[i].h);
}
int l=1,r=1e5;
while(l<=r){
int mid=(l+r)/2;
if(is_ok(mid))l=mid+1;
else r=mid-1;
}
printf("%d\n",l-1);
return 0;
}
简记:本来是线段树扫描线的,暴力冲过去了
#include
using namespace std;
bool book[10005][10005];
int main(int argc,char **argv)
{
int cnt,sum=0;
scanf("%d",&cnt);
while(cnt--)
{
int x1,x2,y1,y2;
scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
int i,j;
for(i=x1;i<x2;i++)
for(j=y1;j<y2;j++)
{
if(book[i][j]==false)
{
book[i][j]=true;
sum++;
}
}
}
printf("%d\n",sum);
return 0;
}
简记:模拟
#include
using namespace std;
struct data{
int y,m,d;
void print(){
printf("%d-%02d-%02d\n",y,m,d);
}
}s,t;
int day[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
bool is_run(int x){
if(x%100==0){
return x%400==0;
}
return x%4==0;
}
data operator +(data x, int ppp){//+1
data ret=x;
ret.d++;
if(ret.d> day[ret.m]+(ret.m==2&&is_run(ret.y))){
ret.d=1;
ret.m++;
if(ret.m==13){
ret.m=1;
ret.y++;
}
}
return ret;
}
bool operator == (data l, data r){
return l.y==r.y&&l.m==r.m&&l.d==r.d;
}
bool operator <= (data l, data r){
if(l.y!=r.y){
return l.y<r.y;
}
if(l.m!=r.m){
return l.m<r.m;
}
return l.d<=r.d;
}
void init(){
s.y=1960; s.m=1; s.d=1;
t.y=2059; t.m=12; t.d=31;
}
int a,b,c;
bool is_ok(data x){
if(x.y%100==a&&x.m==b&&x.d==c)return 1;
if(x.y%100==c&&x.m==a&&x.d==b)return 1;
if(x.y%100==c&&x.m==b&&x.d==a)return 1;
return 0;
}
int main(){
init();
scanf("%d/%d/%d",&a,&b,&c);
for(data i=s;i<=t;i=i+1){
if(is_ok(i)) i.print();
}
return 0;
}
简记:简单维护思想
#include
using namespace std;
const int maxn = 100005;
typedef long long int qq;
int n,a[maxn],c[maxn],s[maxn],k;
int main(){
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
s[i]=(s[i-1]+a[i])%k;
c[s[i]]++;
}
qq ans=0;
for(int i=1;i<=n;i++){
ans+=c[s[i-1]];
c[s[i]]--;
}
printf("%lld\n",ans);
return 0;
}
简记:进制知识
#include
using namespace std;
typedef long long int qq;
int a[100];
int main(){
qq n;
while(scanf("%lld",&n)!=EOF){
int cnt=0;
while(n){
if(n%26==0){
a[cnt++]=26;
n/=26;
n--;
}
else{
a[cnt++]=n%26;
n/=26;
}
}
for(int i=cnt-1;i>=0;i--){
char c='A'+a[i]-1;
printf("%c",c);
}
printf("\n");
}
return 0;
}
简记:dfs暴力搜索即可
#include
using namespace std;
int a[3][3],ans[3][3];
int vis[10],num=0;
bool is_ok(){
int e=(1+9)*9/2;
e/=3;
for(int i=0;i<3;i++){
int s1=0,s2=0;
for(int j=0;j<3;j++){
s1+=a[i][j];
s2+=a[j][i];
}
if(s1!=e||s2!=e)return 0;
}
if(a[0][0]+a[1][1]+a[2][2]!=e)return 0;
if(a[0][2]+a[1][1]+a[2][0]!=e)return 0;
return 1;
}
void out(){
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
printf("%d ",a[i][j]);
}
printf("\n");
}
printf("-----\n");
}
void dfs(int dep){
if(num==2)return;
if(dep==9){
//out();
if(is_ok()){
num++;
for(int i=0;i<3;i++)for(int j=0;j<3;j++){
ans[i][j]=a[i][j];
}
}
return ;
}
int x=dep%3, y=dep/3;
//printf("dep=%d (%d,%d)=%d \n",dep,x,y,a[x][y]);
if(a[x][y]!=0)dfs(dep+1);
else{
for(int i=1;i<=9;i++){
if(vis[i])continue;
a[x][y]=i;
vis[i]=1;
dfs(dep+1);
a[x][y]=0;
vis[i]=0;
}
}
}
int main(){
memset(vis,0,sizeof(vis));
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
scanf("%d",&a[i][j]);
vis[a[i][j]]++;
}
}
dfs(0);
if(num==1){
for(int i=0;i<9;i++){
printf("%d",ans[i/3][i%3]);
if(i%3==2) printf("\n");
else printf(" ");
}
}
else {
printf("Too Many\n");
}
return 0;
}
简记:bfs
#include
using namespace std;
const int bas = 15;
int mov[6]= {-3, -2, -1, 1, 2, 3 }, len;
struct state{
int a[bas],pos,step,hast=-1;
int hash(){
//if(hast!=-1)return hast;
int ret=0;
for(int i=0;i<len;i++){
ret=ret*3+a[i];
//printf("ret=%d\n",ret);
}
return ret;
}
void input(char *s, int n){
for(int i=0;i<n;i++){
if(s[i]=='*'){
a[i]=0;pos=i;
}
if(s[i]=='W') a[i]=1;
if(s[i]=='B') a[i]=2;
}
}
void print(){
printf("%d ",step);
for(int i=0;i<len;i++){
printf("%d",a[i]);
}
printf("\n");
}
};
bool vis[15000000];
queue<state>q;
int bfs(state s, state t, int n){
len=n;
memset(vis,0,sizeof(vis));
vis[s.hash()]=1;
s.step=0;
q.push(s);
int e=t.hash();
while(!q.empty()){
//q.front().print();
if(q.front().hash()==t.hash())return q.front().step;
state now=q.front();
now.step++;
for(int i=0;i<6;i++){
if(now.pos+mov[i]<0 || now.pos+mov[i]>=len)continue;
int t= now.a[now.pos];
now.a[now.pos]=now.a[now.pos+mov[i]];
now.a[now.pos+mov[i]]=t;
now.pos+=mov[i];
now.hast=-1;
int add=now.hash();
if(vis[add]){
t= now.a[now.pos];
now.a[now.pos]=now.a[now.pos-mov[i]];
now.a[now.pos-mov[i]]=t;
now.pos-=mov[i];
now.hast=-1;
continue;
}
vis[add]=1;
q.push(now);
//printf("step=%d\n",now.step);
//printf("@1 ");now.print();
t= now.a[now.pos];
now.a[now.pos]=now.a[now.pos-mov[i]];
now.a[now.pos-mov[i]]=t;
now.pos-=mov[i];
now.hast=-1;
//printf("@2 ");now.print();
}
q.pop();
}
}
int main(){
//printf("%lf\n",pow(3,15));
char temp[100];
state s,t;
scanf("%s",temp);
s.input(temp,strlen(temp));
scanf("%s",temp);
t.input(temp,strlen(temp));
printf("%d\n",bfs(s,t,strlen(temp)));
return 0;
}
简记:两次dfs找环即可,基环树。
#include
using namespace std;
#define maxn 100052
int vis[maxn];
int a[maxn],n,cnt=0,xcx=0,flag=0;
vector<int>u[maxn];
void dfs(int x, int fa){
if(xcx!=0)return;
vis[x]=1;
for(int i=0;i<u[x].size();i++){
if(u[x][i]==fa)continue;
if(vis[u[x][i]]){
xcx=u[x][i];
vis[x]=0;
return ;
}
dfs(u[x][i],x);
}
vis[x]=0;
}
void dfs2(int x,int fa){
if(flag==1)return;
for(int i=0;i<u[x].size();i++){
if(u[x][i]==fa)continue;
if(u[x][i]==xcx){
flag=1;
a[cnt++]=x;
return;
}
//printf("x=%d %d\n",x,u[x][i]);
dfs2(u[x][i],x);
if(flag==1){
a[cnt++]=x;
return;
}
}
vis[x]=0;
}
int main(){
scanf("%d",&n);
for(int i=0;i<n;i++){
int t1,t2;
scanf("%d%d",&t1,&t2);
u[t1].push_back(t2);
u[t2].push_back(t1);
}
dfs(1,0);
memset(vis,0,sizeof(vis));
//printf("%d\n",xcx);
dfs2(xcx,0);
/*for(int i=1;i<=n;i++){
if(vis[i])a[cnt++]=i;
}*/
sort(a,a+cnt);
for(int i=0;i<cnt;i++){
if(i!=0)printf(" ");
printf("%d",a[i]);
}
printf("\n");
return 0;
}