日期 | 事件 | 刷的题 |
---|---|---|
Day 0 星期日 | 做文档,写作业,刷比赛 | 购物券(dfs+hash) |
Day 1 星期一 | 完善了博客 | 无 |
Day 2 星期二 | 讲课 | NOI元旦 |
Day 3 星期三 | 做题 | 格子游戏 |
Day 4 星期四 | 刷题,写博客 | 矩形,搭配购买,旅行,嫌疑犯,宗教,雀斑 |
Day 5 星期五 | 出题 | 无 |
Day 6 星期六 | 模拟赛 | 模拟赛的题 |
题目 | 时间复杂度 |
---|---|
第一题 奇数 | O(to−from2) O ( t o − f r o m 2 ) |
第二题 求和 | O(n−−√+nn−−√) O ( n + n n ) |
第三题 圆环 | O(n+∑i=11..nlog(ai)) O ( n + ∑ 1.. n i = 1 l o g ( a i ) ) |
第四题 翻转 | O(4n2) O ( 4 n 2 ) |
第五题 得分 | O(nlogn+nm) O ( n l o g n + n m ) |
第六题 重要人物 | O(n2+2G+KE) O ( n 2 + 2 G + K E ) |
最水的题,直接暴力。顺便练习下骚库(STL)
#include
#include
using namespace std;int from,to;
vector<int>odd;
int main()
{
scanf("%d%d",&from,&to);//输入
if(!(from&1)) from++;if(!(to&1)) to--;//一些小优化
for(int i=from;i<=to;i+=2) odd.push_back(i);//放入
printf("%d\n",odd.size());//输出数量
for(int i=0;iprintf("%d\n",odd[i]);//输出
}
直接模拟
#include
#define r(i,a,b) for(int i=a;i<=b;i++)
using namespace std;int s,n=1,k,ans[101],p;
bool h[100001];
bool check(int x)//暴力判断
{
if(!x) return true;//正好相等
if(x&1) return false;//不是偶数
x>>=1;//变成一半
if(h[x]) //是否存在
{
ans[++p]=x;
return true;//存在输出
}
r(i,1,n-1)
r(j,i+1,n)
if(i+j==x)//存在
{
ans[++p]=i;
ans[++p]=j;
return true;//继续查找
}
return false;//不存在
}
int main()
{
scanf("%d",&s);
while(k+n1;
k+=n;//暴力高斯定理
do
{
if(check(k-s))//暴力判断
{
printf("%d\n",n);//输出
r(i,1,p) printf("%d\n",ans[i]);//暴力输出
return 0;
}
k+=++n;h[n]=1;//继续找
}while(1);//暴力搜
}
一波暴力的辗转相除法,尽管我是用了骚库(STL)
#include
#include
using namespace std;int n,a,b;
int main()
{
scanf("%d\n%d",&n,&a);//输入
while(--n)//循环
scanf("%d",&b),printf("%d/%d\n",a/__gcd(a,b),b/__gcd(a,b));//输出
}
暴力模拟
翻转三次,每次对应的格子位置为
#include
#define r(i,a,b) for(int i=a;i<=b;i++)
using namespace std;int n,ans;char c;
bool x[4][501][501];
int make(int k,int i,int j)
{
if(k==1) return x[0][j][n-i+1];
if(k==2) return x[0][n-i+1][n-j+1];
if(k==3) return x[0][n-j+1][i];//一波暴力
}
int main()
{
scanf("%d",&n);
r(i,1,n)
{
c=getchar();
r(j,1,n)
{
c=getchar();x[0][i][j]=c=='1';ans+=x[0][i][j];
}//输入不解释
}
printf("%d\n",ans);
r(k,1,3)//翻转三个
{
r(i,1,n)
r(j,1,n)
if(make(k,i,j)>x[k-1][i][j])
x[k][i][j]=make(k,i,j),ans++;//如果能够覆盖
else
x[k][i][j]=x[k-1][i][j];//否则
printf("%d\n",ans);//输出
}
}
20分思路,dfs
30分思路,贪心
100分思路,动态规划+贪心
动态转移方程
#include
#include
#define r(i,a,b) for(int i=a;i<=b;i++)
using namespace std;int n,m,ans;
struct node
{
int t,c;
}p[3001];
bool cmp(node x,node y){return x.t/1.0/x.c1.0/y.c;}//按比例排序
int main()
{
scanf("%d%d",&n,&m);
r(i,1,n) scanf("%d%d",&p[i].t,&p[i].c);
stable_sort(p+1,p+1+n,cmp);
for(int i=1;i<=n;i++)
if(m>=p[i].t)//一波贪心
{
ans+=m*p[i].c;
m-=p[i].t;
}
printf("%d",ans);//输出
}
#include
#include
#define r(i,a,b) for(int i=a;i<=b;i++)
using namespace std;int n,m,ans,f[10001],tot;
struct node
{
int t,c;
}p[3001];
bool cmp(node x,node y){return x.t/1.0/x.c1.0/y.c;}
void dp()//动态规划
{
r(i,1,n)
for(int j=m;j>=p[i].t;j--)
if(f[j-p[i].t]+p[i].c*(m-j+p[i].t)>f[j])
f[j]=f[j-p[i].t]+p[i].c*(m-j+p[i].t);
r(i,1,m)
tot=max(f[i],tot);
}
int main()
{
scanf("%d%d",&n,&m);
r(i,1,n) scanf("%d%d",&p[i].t,&p[i].c);
stable_sort(p+1,p+1+n,cmp);//排序这里用了贪心的思想
dp();
printf("%d",tot);//输出
}
Spfa+预处理
对于大人物走的路,可以一波预处理,把这些路用一个数组来表示。 lazyi,j.begin l a z y i , j . b e g i n 表示第i个点到第j个点大人物进入的起始时间。 lazyi,j.end l a z y i , j . e n d 表示第i个点到第j个点大人物出去的时间。
然后只需要在spfa里面加上这样一个语句
if(dis[u]>=lazy[u][v].begin i f ( d i s [ u ] >= l a z y [ u ] [ v ] . b e g i n && dis[u]<lazy[u][v].end) d i s [ u ] < l a z y [ u ] [ v ] . e n d )
表示如果这条路大人物会经过的话则
#include
#include
#include/*其实这题用邻接表会更好,但为了练习STL库,还是用了vecotr和queue*/
#include
#define r(i,a,b) for(int i=a;i<=b;i++)
using namespace std;int n,m,A,B,K,G,x,y,w,l[1001][1001],dis[1001],p[1001];//p表示大人物经过的城市
struct node
{
int begin,end;
}lazy[1001][1001];//一波结构体
vector<int>g[1001];//一波骚库
void spfa()//一波spfa
{
int from=A;
queue<int>q;q.push(from);//日常骚库
bool vis[1001]={0};vis[from]=true;
dis[from]=K;//这里初始为K,到最后再减
while(!q.empty())
{
int u=q.front();q.pop();vis[u]=true;
r(i,0,g[u].size()-1)
{
int w=l[u][g[u][i]],v=g[u][i];
if(dis[u]>=lazy[u][v].begin&&dis[u]//骚操作
if(dis[u]+wif(!vis[v])
q.push(v),vis[v]=true;//一波spfa
}
}
vis[u]=false;
}
}
int main()
{
scanf("%d%d",&n,&m);
scanf("%d%d%d%d",&A,&B,&K,&G);//输入
r(i,0,n-1)
r(j,i+1,n)
dis[i]=dis[j]=l[i][j]=l[j][i]=536870912;
r(i,1,G) scanf("%d",&p[i]);//输入
r(i,1,m)
{
scanf("%d%d%d",&x,&y,&w);
g[x].push_back(y);
g[y].push_back(x);
l[x][y]=l[y][x]=w;//日常spfa
}
lazy[p[2]][p[1]].begin=lazy[p[1]][p[2]].begin=0;
lazy[p[2]][p[1]].end=lazy[p[1]][p[2]].end=l[p[1]][p[2]];
lazy[p[3]][p[2]].begin=lazy[p[2]][p[3]].begin=lazy[p[1]][p[2]].end;
lazy[p[3]][p[2]].end=lazy[p[2]][p[3]].end=lazy[p[1]][p[2]].end+l[p[2]][p[3]];
r(i,4,G)
{
lazy[p[i-1]][p[i]].begin=lazy[p[i]][p[i-1]].begin=lazy[p[i-1]][p[i-2]].end;
lazy[p[i-1]][p[i]].end=lazy[p[i]][p[i-1]].end=lazy[p[i-1]][p[i]].begin+l[p[i-1]][p[i]];
}//一波lazy操作,只可意会不可言传。
spfa();//spfa
printf("%d",dis[B]-K);//输出
}