数论只会GCD 模拟只会猜题意 贪心只能过样例!!!!!
上午身体不适,基本上是强行趴在那写题。也不知道思路在哪个状态,看到T1第一想法居然连暴力都不是了。第一想法,居然是打表2333
T1: 计算系数
为什么我脑子里第一反应是打表…
是的这是我用画图打的草稿(还有一部分打到草稿纸上了)
然后我就写出来以下的天秀打表
// if(a==b&&b==1){
// if(k<=10){
// switch(k){
// case 0:{
// cout<<0;
// break;
// }
// case 1:{
// cout<<0;
// break;
// }
// case 2:{
// if(n==0||m==0){
// //2+0
// cout<<1;
// }
// else if(n==1){
// //1+1
// cout<<2;
// }
// else{
// cout<<0;
// }
// break;
// }
// case 3:{
// if(n==0||m==0){
// cout<<1;// 3+0
// }
// else if(n==2||m==2){
// //2+1
// cout<<3;
// }
// else{
// cout<<0;
// }
// break;
// }
// case 4:{
// if(n==3||m==3){
// //3+1
// cout<<4;
// }
// else if(n==2){
// cout<<6;
// //2+2
// }
// else if(n==0||m==0){
// cout<<1;//4+0
// }
// else{
// cout<<0;
// }
// break;
// }
// case 5:{
// if(n==4||m==4){//4+1
// cout<<5;
// }
// else if(m==2||n==2){
// //3+2
// cout<<10;
// }
// else if(m==0||n==0){
// //5+0
// cout<<1;
// }
// else{
// cout<<0;
// }
// break;
// }
// case 6:{
// if(n==5||m==5){
// cout<<6;//5+1
// }
// else if(m==0||n==0){
// //6+0
// cout<<1;
// }
// else if(m==2||n==2){//4+2
// cout<<15;
// }
// else if(m==3){//3+3
// cout<<20;
// }
// else{
// cout<<0;
// }
// break;
// }
// case 7:{
// if(n==6||m==6){
// cout<<7;//6+1
// }
// else if(n==0||m==0){
// cout<<1;
// //7+0
// }
// else if(m==2||n==2){//5+2
// cout<<21;
// }
// else if(m==3||n==3){//4+3
// cout<<35;
// }
// else{
// cout<<0;
// }
// break;
// }
// case 8:{
//
// break;
// }
// case 9:{
//
// break;
// }
// case 10:{
//
// break;
// }
// }
// }
// else{
//
// }
// }
打到8的时候,终于打通了我的脑回路。打表找规律…这行为是真滴流氓。
果然跟这个题目差不多,factor,类似于因子嘛(别挖我的十五级英语!!!),然后就发觉这东西是和前一项有联系的(而且还是相加的关系!)就是说,你的这个因子总是与上一个数的因子相关联。我就…痴痴地写出了以下正解…
#include<iostream>
#include<algorithm>
using namespace std;
long long a,b,k,n,m;
long long A[2000][2000];
long long ans;
const int Mogic=10007;
int power(int a,int b){
int ans=1;
for(;b;b>>=1){
if(b&1){
ans=(long long)ans*a%Mogic;
}
a=(long long)a*a%Mogic;
}
//cout<<"返回值为"<<ans<<endl;
return ans;
}
int main(){
freopen("factor.in","r",stdin);
freopen("factor.out","w",stdout);
cin>>a>>b>>k>>n>>m;
A[2][2]=1;A[2][0]=1;
A[2][1]=2;
for(int j=3;j<=k;j++){
A[j][0]=1;
A[j][j]=1;
A[j][j-1]=j;
A[j][1]=j;
}
//对于每个数来说
//他的 i分子与 k-i是相同的
for(int x=4;x<=k;x++){
for(int i=2;i<=k/2;i++){
A[x][i]=A[x-1][i]+A[x-1][x-i];
A[x][i]%=Mogic;
A[x][x-i]=A[x][i];
}
}
if(a==b&&b==1){
cout<<A[k][n]%Mogic;
}
else{
//cout<<"调用二号"<<endl;
A[k][n]%=Mogic;
a%=Mogic;
b%=Mogic;
long long dele;
dele=power(a,n)*power(b,m);
dele%=Mogic;
//cout<<"dele为 "<<dele<<endl;
//cout<<"A k n "<<A[k][n]<<endl;
ans=A[k][n]*dele;
ans%=Mogic;
cout<<ans;
}
}
记着开LongLong!
T2: 聪明的质监员
这个质检员的形容词是聪明?
一股腐败气息(哼)
当时拿到之后脑子还是懵兮兮的,直接跟着题走去模拟了。
#include<iostream>
#include<cmath>
#include<cstdio>
using namespace std;
const int MAXN=999999;
int n,m,s;
int w[MAXN];
int V[MAXN];
struct Factory{
int a;
int b;
}Zone[MAXN];
int ans;
int res;
bool Good[MAXN];
int main(){
//freopen("qc.in","r",stdin);
//freopen("qc.out","w",stdout);
res=9999999;
int maxx=0;
int maxx_forzone=0;
int minxx_forzone=900;
cin>>n>>m>>s;
for(int i=1;i<=n;i++){
cin>>w[i]>>V[i];
maxx=max(maxx,w[i]);
}
int x,y;
for(int i=1;i<=m;i++){
cin>>x>>y;
Zone[i].a=x;
Zone[i].b=y;
maxx_forzone=max(maxx_forzone,y);
minxx_forzone=min(minxx_forzone,x);
}
for(int W=1;W<=maxx;W++){
//这题估计用二分
//二分这个W,找到一个会产生正数差和负数差的平衡点
//只要这个W一大,那么相应的ans值就会减小。也就是说,
//当二分出差值一正一副的时候,对比两边的差值,得出最终答案。
ans=0;
for(int i=minxx_forzone;i<=maxx_forzone;i++){
if(w[i]>=W){
Good[i]=true;
}
else{
Good[i]=false;
}
}
for(int i=1;i<=m;i++){
int tot=0;
int val=0;
for(int j=Zone[i].a;j<=Zone[i].b;j++){
if(Good[i]){
tot++;
val+=V[j];
}
}
ans+=tot*val;
// if(s-ans<0&&abs(s-ans)>res){
// break;
// }
int index=abs(s-ans);
res=min(res,index);
}
//cout<<"选择了 "<<W<<" 所产生的区间和为 "<<ans<<endl;
}
cout<<res;
}
最有趣的是写着写着忽然就醒悟“哦!这是道二分题!!”
然后看了一眼表“我去我第一题是模拟了多久…还剩十分钟…算了把这题打完拉倒了,不管二分的事了”
喜爆零~!(好像是有个题目意思理解错了吗?)
正解其实也就是二分+前缀和了。没办法T1玩的太嗨,T2有思路了也没用。
#include<iostream>
#include<cstring>
#include<cmath>
#include <stdlib.h>
using namespace std;
const int MAXN=2000010;
int n,m;
long long ans;
long long S;
long long MAX_forR;
long long MIN_forL;
long long w[MAXN];
long long v[MAXN];
struct section{
int l;
int r;
}Zone[MAXN];
long long Y,sum;
long long FrontSum_n[MAXN];//你瞧,英语十级的气息
long long FrontSum_v[MAXN];
bool check(int W){
Y=0;sum=0;
memset(FrontSum_n,0,sizeof(FrontSum_n));
memset(FrontSum_v,0,sizeof(FrontSum_v));
for(int i=1;i<=n;i++){
if(w[i]>=W){
FrontSum_n[i]=FrontSum_n[i-1]+1;
FrontSum_v[i]=FrontSum_v[i-1]+v[i];
}
else{
FrontSum_n[i]=FrontSum_n[i-1];
FrontSum_v[i]=FrontSum_v[i-1];
}
}
for(int i=1;i<=m;i++){
Y+=(FrontSum_n[Zone[i].r]-FrontSum_n[Zone[i].l-1])*(FrontSum_v[Zone[i].r]-FrontSum_v[Zone[i].l-1]);
}
sum=llabs(Y-S);
if(Y>S){
return true;
}
else{
return false;
}
}
int main(){
cin>>n>>m>>S;
MIN_forL=999999999;
ans=999999999999999;
for(int i=1;i<=n;i++){
cin>>w[i]>>v[i];
MAX_forR=max(MAX_forR,w[i]);
MIN_forL=min(MIN_forL,w[i]);
}
for(int i=1;i<=m;i++){
cin>>Zone[i].l;
cin>>Zone[i].r;
}
int left=MIN_forL-1;
int right=MAX_forR+2;
int mid;
while(left<=right){
mid=(left+right)/2;
if(check(mid)){
left=mid+1;
}
else{
right=mid-1;
}
if(sum<ans){
ans=sum;
}
}
cout<<ans;
}
(话说long long设定个最大值是真的麻烦…那个9写少了居然能炸一半的数据…)
T3: 观光公交
考场的时候没看,毕竟时间没了。
下来之后看了看题,感觉上来说…有点像以前做过的一个缆车的题…但又不一样。
这里有一个逻辑上的点,就是如果你开了氮气加速但到站了仍然需要等待最后一个来的人,那这波氮气就开的挺亏的。
公交车氮气加速,你这怕是速度与激情,牛逼!
代码来自LuoGu题解,看懂了但是真的不想再重新写一遍了…
/*last[ i ] : 最后一个人到达i站点的时间。
sum[ i ] : 到i站点的总人数。
enter[ i ] : 公交车到i站点的最少时间。
g[ i ] : 每个站点所能影响到的最远站点,即要求的影响。*/
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
//完全get,但精神受到了昨天175行重构代码结果有Bug没法Debug的重创
//今天!决定!不!重!构!啦!
#define N 30001
using namespace std;
int n,m,k;
int dis[N],last[N],g[N],enter[N];
int ans,sum[N],maxx = -1;
struct node{
int time,start,end;
}a[N];
inline void bus(int x){
while(x){
--x;
g[n] = g[n - 1] = n;
int tar;
maxx = -1;
for(int i = n - 2;i >= 1;-- i){
if(enter[i + 1] <= last[i + 1])//下一个点如果等待
g[i] = i + 1;//最多影响到下一个
else //不等待
g[i] = g[i + 1];//继续减少后面的时间
}
for(int i = 1;i < n;++ i){//for边数
int tmp = sum[g[i]] - sum[i];//最多影响的人数
if(tmp > maxx && dis[i] > 0){
maxx = tmp;
tar = i;//标记最优情况减的点
}
}
ans -= maxx;//更新ans
dis[tar] --;//减掉dis
for(int i = 2;i <= n;++ i){
enter[i] = max(enter[i - 1],last[i - 1]) + dis[i - 1];//重新更新enter
}
}
return;
}
int main(){
scanf("%d%d%d",&n,&m,&k);//
for(int i = 1;i < n;++ i)
scanf("%d",&dis[i]);//
for(int i = 1;i <= m;++ i)
scanf("%d%d%d",&a[i].time,&a[i].start,&a[i].end);
for(int i = 1;i <= m;++ i){
last[a[i].start] = max(last[a[i].start],a[i].time);//最后一个人到a[i].start站点的时间 和到这个点的时间取max
sum[a[i].end] ++;
}
enter[1] = last[1];
for(int i = 1;i <= n;++ i)
sum[i] += sum[i - 1];//到i站点的总人数 前缀和处理
for(int i = 2;i <= n;++ i)
enter[i] = max(enter[i - 1],last[i - 1]) + dis[i - 1];//公车到i站点的最少时间 和最后到的时间取max
for(int i = 1;i <= m;++ i)
ans += enter[a[i].end] - a[i].time;//处理出不加加速器的answer,后面就可以直接减啦~
bus(k);
printf("%d",ans);
return 0;
}//