2016多校7.14 Warmup 题解
先讲1007,是一个数位dp,询问一个区间内,各位数的和是一个素数的数字的个数。其实我并不会数位dp,这题直接套用了上次多校lyf队长的dp代码,改了点返回参数没想到直接AC了。代码如下:
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <iostream>
#include <vector>
#include <queue>
#include <math.h>
using namespace std;
typedef long long ll; int bit[];
ll dp[][]; bool isprime[]; void getPrimeTable()
{
memset(isprime,,sizeof(isprime));
isprime[]=;
for(int i=;i<;i++)
{
if(isprime[i])
{
for(int j=*i;j<;j+=i)
{
isprime[j]=false;
}
}
}
} ll dfs(int pos,int sum,bool flag)
{
if(pos == -) return (ll)isprime[sum];
ll& ans = dp[pos][sum];
if(flag && ans!=-) return ans;
int d = flag?:bit[pos]; ll ret = ;
for(int i=;i<=d;i++)
{
ret += dfs(pos-,sum+i,flag||i<d);
}
if(flag) ans = ret;
return ret;
} ll solve(ll x)
{
int pos = ;
while(x)
{
bit[pos++] = x % ;
x /= ;
} ll ans = ;
ans += dfs(pos-,,false);
return ans;
} int main()
{
getPrimeTable();
int T;
scanf("%d",&T);
memset(dp,-,sizeof(dp));
for(int kase=;kase<=T;kase++)
{
ll x,y;
scanf("%I64d%I64d",&x,&y);
printf("%I64d\n",solve(y)-solve(x-));
}
}
从这个来看,看来以后对于各个位数上的和能够满足某一条件的数位dp,都可以直接套用这个模板了。顺便给下上次那个数位dp的AC代码。那题的题意是求区间上满足各位数上的和能被这个数整除的数的个数。代码如下:
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <iostream>
#include <vector>
#include <queue>
#include <math.h>
using namespace std;
typedef long long ll; int bit[],dp[][][][]; int dfs(int pos,int sum,int res,int mod,bool flag)
{
if(pos == -) return sum==mod && res==;
int& ans = dp[pos][sum][res][mod];
if(flag && ans!=-) return ans;
int d = flag?:bit[pos]; int ret = ;
for(int i=;i<=d;i++)
{
ret += dfs(pos-,sum+i,(res*+i)%mod,mod,flag||i<d);
}
if(flag) ans = ret;
return ret;
} int solve(int x)
{
int pos = ;
while(x)
{
bit[pos++] = x % ;
x /= ;
} int ans = ;
for(int i=;i<=;i++) ans += dfs(pos-,,,i,false);
return ans;
} int main()
{
int T;
scanf("%d",&T);
memset(dp,-,sizeof(dp));
for(int kase=;kase<=T;kase++)
{
int x,y;
scanf("%d%d",&x,&y);
printf("Case %d: %d\n",kase,solve(y)-solve(x-));
}
}
1004,是一个模拟题,只要搞懂了题意就行,还好队友玩过了炉石传说,所以这题顺理成章的很快就1A了。要注意的是,mana值是没用的,有护甲的时候先扣护甲,再扣血;血有上限为30,护甲没有,在你我这样的一个大回合里,每个回合扣血数加1。具体见代码(现场上交的,没做过修改):
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <iostream>
#include <vector>
#include <queue>
#include <math.h>
using namespace std;
typedef long long ll; struct player
{
int hp,r;
int id;
}G[]; void sub(int pl,int down)
{
if(G[pl].r>=down) G[pl].r-=down;
else
{
G[pl].hp-=(down-G[pl].r);
G[pl].r=;
}
} void usepow(int pl)
{
int id = G[pl].id;
if(id == || id==)
{
sub(-pl,id);
//G[3-pl].hp-=id;
}
else if(id == )
{
G[pl].r+=;
}
else
{
G[pl].hp+=;
if(G[pl].hp>) G[pl].hp=;
}
} int main()
{
int T;
scanf("%d",&T);
while(T--)
{
for(int i=;i<=;i++)
scanf("%d%d%d",&G[i].id,&G[i].hp,&G[i].r);
int cnt = ;
int flag = ;
for(;;)
{
sub(,cnt);
//G[1].hp-=cnt;
if(G[].hp<=)
{
flag = ;
break;
}
usepow();
if(G[].hp<=)
{
flag = ;
break;
} sub(,cnt);
//G[2].hp-=cnt;
if(G[].hp<=)
{
//flag = 0;
break;
}
usepow();
if(G[].hp<=)
{
//flag = 0;
break;
}
cnt++;
}
puts(flag?"YES":"NO");
}
}
1008是一个按照税法缴税的水题,但是当时题目数据给错了,所以WA倒一片。有意思的是我当时去百度了一下,找到了缴税百分比的表格,却没有发现最后一个数据是不同的!!- -,这题也真是有趣啊。。代码如下(大力学长的代码):
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <set>
#include <math.h>
#include <vector>
#include <stack>
#include <map>
#include <string.h>
#define t_mid (l+r>>1)
#define ls (o<<1)
#define rs (o<<1 | 1)
#define lson ls,l,t_mid
#define rson rs,t_mid+1,r
const double eps = 1e-;
using namespace std;
typedef long long ll;
int T;
double x;
double money[] = {,,,,,,};
double rate[] = {0.03,0.1,0.2,0.25,0.3,0.35,0.45};
int sgn(double x){ return x < -eps ? - : x > eps ? : ;}
int main(){
cin >> T;
while(T--){
scanf("%lf",&x);
double amount = ;
x -= 3500.0;
int pos = ;
while(sgn(x) > && pos <= ){
if(x > money[pos]){
amount += (money[pos] - money[pos-]) * rate[pos-];
pos ++;
}else{
amount += (x - money[pos-]) * rate[pos-];
pos ++;
break;
}
}
if(sgn(x - 80000.0) > )
amount += (x - 80000.0) * 0.45;
printf("%.2f\n",amount);
}
return ;
}
1006是一个很烦的题目,题意是给出若干个点,问存在多少个矩形,它们的边都是水平或者垂直的,且四个角上都包含了点。思路是,先想办法存下离散化后的图,然后对每一列,往下推m-1行,分别找这两行往后推m-1列的纵坐标的值是否相等,若相等,则个数加1。具体见代码(有注释):
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <queue>
#include <vector>
#include<iostream>
using namespace std;
const int N = ;
const int inf = 0x3f3f3f3f;
typedef pair<int,int> pii;
typedef long long ll; struct point
{
int x,y;
};
point po[N]; vector<int> G[N];
vector<int> RG[N]; bool cmp1(point a,point b) {return a.x==b.x?a.y<b.y:a.x<b.x;}
bool cmp2(point a,point b) {return a.y==b.y?a.x<b.x:a.y<b.y;} /*
xx,yy,代表当前坐标
返回这个坐标同一个横坐标上面第m个点的纵坐标
*/
int Find(int xx,int yy,int m,int mx)
{
int L = ,R = mx,mid;
while(L<=R)
{
mid = R + L >> ;
if(RG[mid][] < xx)
L = mid + ;
else if(RG[mid][] > xx) R = mid - ;
else break;
} int now = mid; // now是找到的当前行
if(L > R) return inf;
L = ;
R = RG[now].size() - ; while(L<=R)
{
mid = R + L >> ;
if(RG[now][mid]<yy)
L = mid + ;
else if(RG[now][mid]>yy) R = mid - ;
else break;
}
if(mid + m- <= RG[now].size()-)
return RG[now][mid+m-];
else return inf;
} int main()
{
int t;
cin >> t;
while(t--)
{
int n,m;
scanf("%d%d",&n,&m);
for(int i = ;i < n;i ++)
{
G[i].clear();
RG[i].clear();
} for(int i= ;i <n;i ++) scanf("%d%d",&po[i].x,&po[i].y); if(m <= )
{
cout << << endl;
}
else
{
sort(po,po+n,cmp1);
/*
cmp1是按照x的大小排序
*/
int cnt = ;
/*
RG里面放的是某一行里面的所有y值,
同时,第一个元素是这一行的x值是多少
*/
RG[cnt].push_back(po[].x);
RG[cnt].push_back(po[].y);
for(int i= ;i < n;i ++)
{
point now = po[i];
if(now.x > RG[cnt][])
{
cnt++;
RG[cnt].push_back(po[i].x);
RG[cnt].push_back(po[i].y);
}
else
{
RG[cnt].push_back(po[i].y);
}
} /*
G里面存放的元素和RG正好相反,
存某一列里面的所有x值,
同时,第一个元素是这一列的y值是多少
*/
sort(po,po+n,cmp2);
int cnt2 = ;
G[].push_back(po[].y);
G[].push_back(po[].x);
for(int i= ;i < n;i ++)
{
point now = po[i];
if(now.y > G[cnt2][])
{
cnt2 ++;
G[cnt2].push_back(now.y);
G[cnt2].push_back(now.x);
}
else
{
G[cnt2].push_back(now.x);
}
}
int sum= ;
for(int i= ;i + m- <= cnt2;i ++)
{
int yy = G[i][]; //yy表示的是第i列的y值是多少
for(int j = ;j + m - < G[i].size();j ++)
{
//j从1开始,是因为0是用来存放y值的,而不是这一列变化的x值
int xx = G[i][j]; //这一列的第j个的x值
int mm = Find(xx,yy,m,cnt); // 在当前行上找后面的第m-1个位置是否存在,
// 存在的话返回的是那个位置的纵坐标的值
int nn = Find(G[i][j+m-],yy,m,cnt); // 往下m-1行后面的第m-1个位置是否存在
if(mm!= inf&& mm == nn) // 返回inf表示的是不存在
{
sum++;
}
}
}
cout << sum << endl;
}
}
return ;
}
这题是队友做出来的,这里放一下他的源代码(我们的二分写法不太一样- -,队友的数据结构真心强。躺了。。):
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <queue>
#include <vector>
#include<iostream>
using namespace std;
const int N = ;
const int inf = 0x3f3f3f3f;
typedef pair<int,int> pii;
typedef long long ll; struct point
{
int x,y;
};
point po[N]; vector<vector<int> > G(N);
vector<vector<int> > RG(N); bool cmp1(point a,point b)
{
if(a.x<b.x) return ;
else if(a.x > b.x) return ;
else
{
if(a.y < b.y) return ;
return ;
}
} bool cmp2(point a,point b)
{
if(a.y<b.y) return ;
else if(a.y > b.y) return ;
else
{
if(a.x <= b.x) return ;
return ;
}
} int Find(int xx,int yy,int m,int mx)
{
int L = ,R=mx+;
while(R-L>)
{
int mid = (R+L) /;
if(RG[mid][] <= xx)
L = mid;
else R = mid;
}
int now = L;
if(RG[now][] != xx) return ;
L = ;
R = RG[now].size(); while(R-L>)
{
int mid = (R+L)/;
if(RG[now][mid] <= yy)
L = mid;
else R = mid;
}
if(L + m- < RG[now].size())
return RG[now][L+m-];
else return ;
} int main()
{
int t;
cin >> t;
while(t--)
{
int n,m;
scanf("%d%d",&n,&m);
for(int i = ;i < n;i ++)
{
G[i].clear();
RG[i].clear();
} for(int i= ;i <n;i ++)
scanf("%d%d",&po[i].x,&po[i].y);
if(m <= )
{
cout << << endl;
}
else
{
sort(po,po+n,cmp1);
int cnt = ;
RG[cnt].push_back(po[].x);
RG[cnt].push_back(po[].y);
for(int i= ;i < n;i ++)
{
point now = po[i];
if(now.x > RG[cnt][])
{
cnt++;
RG[cnt].push_back(po[i].x);
RG[cnt].push_back(po[i].y);
}
else
{
RG[cnt].push_back(po[i].y);
}
}
sort(po,po+n,cmp2);
int cnt2 = ;
G[].push_back(po[].y);
G[].push_back(po[].x);
for(int i= ;i < n;i ++)
{
point now = po[i];
if(now.y > G[cnt2][])
{
cnt2 ++;
G[cnt2].push_back(now.y);
G[cnt2].push_back(now.x);
}
else
{
G[cnt2].push_back(now.x);
}
}
int sum= ;
for(int i= ;i <= cnt2;i ++)
{
int yy = G[i][];
if(i + m- > cnt2) break;
for(int j = ;j + m - < G[i].size();j ++)
{
int xx = G[i][j];
int mm = Find(xx,yy,m,cnt);
int nn = Find(G[i][j+m-],yy,m,cnt);
//cout << xx << ' ' << yy << ' ' << nn << ' ' << mm << endl;
if(mm!= && mm == nn)
{
//cout << xx <<' ' << yy << endl;
sum++;
} }
}
cout << sum << endl;
} }
return ;
}
/*
12
12 2
1 1
2 1
3 1
4 1
5 1
1 2
2 2
3 2
4 2
5 2
3 3
4 3 -2 1
-2 -1
-1 1
-1 -1
-2 -2
-1 -2
1 1
1 -1
2 1
2 -1
*/
然后是1003,也是队友的奥义思路,然后结合了大力的大数java搞出来的。这题的题意是,给出n个操作,对自然数序列(1,2,3,4...)每个操作保留A[i]个数,删除A[i]个数。问n个操作以后剩下的第n个数是多少。思路是,反推,比方说当前这个数的位置是n,那么如果这一次操作A[i]>=n,那么这一次操作回推的话,n一定还是这个位置,因为这次操作都是删除了后面的数;否则,就在前面插入若干段A[i]就可以了。具体细节见代码吧。
C语言版的(这是WA的,因为没有考虑大数,说到大数我才想起来之前kuangbin的那个大数模板并不太好用。。因为他把“0”用“”代替了,下次再找一份好一点的大数模板吧。。):
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <queue>
#include <vector>
#include<iostream>
using namespace std;
const int N = +;
const int inf = 0x3f3f3f3f;
typedef pair<int,int> pii;
typedef long long ll;
int A[];
int main()
{ int t;
cin >> t;
while(t--)
{
int n;
scanf("%d",&n);
for(int i= ;i <= n;i ++)
scanf("%d",&A[i]);
int sum= n;
for(int i= n;i >= ;i --)
{
if(A[i] >= sum)
continue;
else
{
/*sum = sum + (sum / A[i]-1) * A[i] ;
if(sum%A[i])
sum += A[i];*/
// 上面是队友写的,下面是我自己补题时写的,其实一样的- -
if(sum % A[i])
{
sum += (sum/A[i])*A[i];
}
else sum += (sum/A[i]-)*A[i]; }
//cout << n - i +1<< ' ' << sum << endl;
}
cout << sum << endl;
} return ;
}
Java版的(AC代码):
import java.math.BigInteger;
import java.util.Scanner; public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
Integer t = scanner.nextInt();
int n;
int a[] = new int[10005];
while(t > 0){
n = scanner.nextInt();
for(int i = 1 ; i <= n ; i ++){
a[i] = scanner.nextInt();
}
BigInteger sum = new BigInteger(String.valueOf(n));
for(int i = n ; i >= 1 ; i --){
String str = String.valueOf(a[i]);
BigInteger aa = new BigInteger(str);
if(aa.compareTo(sum) >= 0) continue;
else{
BigInteger bbb = sum.divide(aa);
BigInteger ccc = bbb.subtract(BigInteger.ONE);
BigInteger ddd = ccc.multiply(aa);
sum = sum.add(ddd);
int eee = sum.remainder(aa).intValue();
if(eee > 0){
sum = sum.add(aa);
}
}
}
System.out.println(sum);
t --;
}
}
}
接着是1002,给出n个点,问是否存在一个圆,使得至少n/3的点在这个圆上。方法是随机取3个点,由三点共圆找出圆心和半径,之后判断。关于随机的方法是否成立的问题,是这样分析的:如果存在这么一个圆,至少n/3的点在这个圆上面,那么也就是说每个点至少有1/3的概率被选到是存在与这个圆上的,那么3个点都是在这个圆上的概率是1/27,反过来,取1次这三个点至少有一个点不在这个圆上的概率是26/27,那么取n次,每次取3个点,每次这3个点都不满足三个点都在这个圆上的概率是(26/27)^n,那么至少有一次满足三个点都在圆上的概率为1-(26/27)^n,而测试数据有20组,所以这个值再来20次幂就是取n次每次随机取3个点这样来判断是否存在这么一个圆的正确率。显然,时间和正确率都和n的取值有关,经测验,n=600左右就已足够(虽然标程给的是n=800)。不管怎样,这个随机的方法真的是厉害啊- -。代码如下(标程):
//shjj-Cir #include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <ctime> using namespace std; const double eps=1e-;
double X[],Y[];
int n,Lim;
double sqr(double x)
{
return x*x;
} void Cir(double ax,double ay,double bx,double by,double cx,double cy,double &x,double &y)
{
double a1=atan2(by-ay,bx-ax)+acos(-.)/;
double a2=atan2(cy-by,cx-bx)+acos(-.)/;
ax=(ax+bx)/,ay=(ay+by)/;
bx=(cx+bx)/,by=(cy+by)/;
double r=(sin(a2)*(ax-bx)+cos(a2)*(by-ay))/(sin(a1)*cos(a2)-sin(a2)*cos(a1));
x=ax+r*cos(a1),y=ay+r*sin(a1);
} int main()
{
//freopen("circle.in","r",stdin);
//freopen("circle.out","w",stdout);
srand(time());
int T;scanf("%d",&T);
for (;T--;)
{
scanf("%d",&n);
for (int i=;i<=n;i++) scanf("%lf%lf",&X[i],&Y[i]);
Lim=n/;
bool P=;
for (int ii=;ii;ii--)
{
int t1=rand()%n+;
int t2=rand()%n+;
for (;t2==t1;t2=rand()%n+);
int t3=rand()%n+;
for (;t3==t1||t3==t2;t3=rand()%n+);
double Xx,Yy,R;
Cir(X[t1],Y[t1],X[t2],Y[t2],X[t3],Y[t3],Xx,Yy);
R=sqr(X[t3]-Xx)+sqr(Y[t3]-Yy);
int ss=;
for (int j=;j<=n;j++)
{
if (fabs(sqr(X[j]-Xx)+sqr(Y[j]-Yy)-R)<eps) ss++;
if (ss>=Lim) break;
}
if (ss>=Lim)
{
P=;
break;
}
}
if (P) puts("YOUGE");
else puts("NIUGE");
}
}
2016多校7.14 Warmup 题解的更多相关文章
- 2016多校第六场题解(hdu5793&hdu5794&hdu5795&hdu5800&hdu5802)
这场就做出一道题,怎么会有窝这么辣鸡的人呢? 1001 A Boring Question(hdu 5793) 很复杂的公式,打表找的规律,最后是m^0+m^1+...+m^n,题解直接是(m^(n+ ...
- 2016年12月14日 星期三 --出埃及记 Exodus 21:9
2016年12月14日 星期三 --出埃及记 Exodus 21:9 If he selects her for his son, he must grant her the rights of a ...
- 2016年11月14日 星期一 --出埃及记 Exodus 20:5
2016年11月14日 星期一 --出埃及记 Exodus 20:5 You shall not bow down to them or worship them; for I, the LORD y ...
- 2016年10月14日 星期五 --出埃及记 Exodus 18:25
2016年10月14日 星期五 --出埃及记 Exodus 18:25 He chose capable men from all Israel and made them leaders of th ...
- 关于苹果开发证书失效的解决方式(2016年2月14日Failed to locate or generate matching signing assets)
前言: 从2月14日開始,上传程序的同学可能会遇到提示上传失败的提示. 而且打开自己的钥匙串,发现所有的证书所有都显示此证书签发者无效. Failed to locate or generate ma ...
- HDU 5732 Subway(2016多校1J,树的重心 + 哈希)
题目链接 2016多校1 Problem J 题意 给定两棵相同的树,但是编号方案不同.求第一棵树上的每个点对应的第二棵树上的点.输出一种方案即可. 首先确定树的直径的中点.两棵树相等意味着两棵树 ...
- 2016 华南师大ACM校赛 SCNUCPC 非官方题解
我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...
- 2016 Multi-University Training Contest 1 部分题解
第一场多校,出了一题,,没有挂零还算欣慰. 1001,求最小生成树和,确定了最小生成树后任意两点间的距离的最小数学期望.当时就有点矛盾,为什么是求最小的数学期望以及为什么题目给了每条边都不相等的条件. ...
- hdu 5723 Abandoned country(2016多校第一场) (最小生成树+期望)
Abandoned country Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others ...
随机推荐
- IDEA的常见的设置和优化(功能)
转载 原文:https://blog.csdn.net/zeal9s/article/details/83544074
- hdu 4826 三维dp
dp的问题除了递推过程的设计之外 还有数据结构的选择以及怎样合理的填充数据 这个的填充是个坑..#include<iostream> #include<cstdio> #inc ...
- Redis 的订阅发布(PUB/SUB)示例
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("127.0.0.1"); ISubscriber sub ...
- JS写斐波那契数列的几种方法
斐波那契数,指的是这样一个数列:1.1.2.3.5.8.13.21.……在数学上,斐波那契数列以如下被以递归的方法定义:F0=0,F1=1,Fn=Fn-1+Fn-2(n>=2,n∈N*),用文字 ...
- css 对div用hover设置border,出现抖动和div走位问题,解决方法
样式设置 : div:hover { border:1px solid red;} 当鼠标移动到div时,产生抖动和偏移. 产生的原因: 是因为设置border时设置了1px边框,多出的这1px,与其 ...
- asp.net mvc 导出Excel
[HttpGet] public void ExportNissan(string CheckListNo) { JObject queryParam; if (CheckListNo == null ...
- android项目笔记整理(2)
31.利用SharedPreferences存储时间 读取时间: SharedPreferences sp=this.getSharedPreferences("actm&q ...
- Django项目实战—分页
自定义分页 未封装版: 优点:直观 缺点:代码乱,不易维护,可拓展性差 data = [] for i in range(1, 302): tmp = {"id": i, &quo ...
- Google 停止推出 Chrome 79
据 Google 方面表示,新版本的使用率达到了整个用户群的 50% 已经.不过值得注意的是,并非所有提供该更新的设备都已安装了该工具.初步数据显示,只有 10% 的人部署了新版本. 针对用户反馈,开 ...
- [Abp vNext微服务实践] - 业务开发
前几篇分别介绍了abp vNext微服务框架.开发环境搭建和vue element admin前端框架接入,在vue element admin中实现用户角色管理基本功能后就可以开始进行业务开发了,本 ...