先讲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 题解的更多相关文章

  1. 2016多校第六场题解(hdu5793&hdu5794&hdu5795&hdu5800&hdu5802)

    这场就做出一道题,怎么会有窝这么辣鸡的人呢? 1001 A Boring Question(hdu 5793) 很复杂的公式,打表找的规律,最后是m^0+m^1+...+m^n,题解直接是(m^(n+ ...

  2. 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 ...

  3. 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 ...

  4. 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 ...

  5. 关于苹果开发证书失效的解决方式(2016年2月14日Failed to locate or generate matching signing assets)

    前言: 从2月14日開始,上传程序的同学可能会遇到提示上传失败的提示. 而且打开自己的钥匙串,发现所有的证书所有都显示此证书签发者无效. Failed to locate or generate ma ...

  6. HDU 5732 Subway(2016多校1J,树的重心 + 哈希)

    题目链接  2016多校1 Problem J 题意  给定两棵相同的树,但是编号方案不同.求第一棵树上的每个点对应的第二棵树上的点.输出一种方案即可. 首先确定树的直径的中点.两棵树相等意味着两棵树 ...

  7. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  8. 2016 Multi-University Training Contest 1 部分题解

    第一场多校,出了一题,,没有挂零还算欣慰. 1001,求最小生成树和,确定了最小生成树后任意两点间的距离的最小数学期望.当时就有点矛盾,为什么是求最小的数学期望以及为什么题目给了每条边都不相等的条件. ...

  9. hdu 5723 Abandoned country(2016多校第一场) (最小生成树+期望)

    Abandoned country Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others ...

随机推荐

  1. SqlServer2008 R2发布订阅

    网上好多大神写的贴子,自己也看着贴子弄的,写的已经很详细了,我就不重复写了,贴上参考资料: http://www.cnblogs.com/dudu/archive/2010/08/26/1808540 ...

  2. CodeFirst与EntityFramework【续】

    3.    实现一对一的关系.在介绍一对多关系和多对多关系时,大家应该已经注意到了只要存在依赖关系的两个类的定义中包含对方的实例或实例的集合,Entity Framework Code First会自 ...

  3. php--最新正则(手机号码)

    这次给大家带来正则验证(2018最新最全手机号验证),正则验证(2018最新最全手机号验证)的注意事项有哪些,下面就是实战案例,一起来看一下. 下面给大家分享2018手机号正则表达式验证方法,具体内容 ...

  4. ant-design的Table组件自定义空状态

    Table,是antd中一个我们经常使用的组件,在官方文档中给出了非常详细的实例以及API, 但在我们在使用过程中可能需要根据项目的要求来定制空状态时的展示. 什么是空状态呢? 在antd的官方文档中 ...

  5. css3控制字体动态变换颜色

    css3控制字体动态变换颜色 <!doctype html> <html> <head> <meta charset="utf-8"> ...

  6. static{}静态代码块与{}普通代码块之间的区别

    先看一个例子: //class A package com.my.test; class A { static { System.out.println("A1:父类静态代码区域" ...

  7. 【Java并发】锁机制

    一.重入锁 二.读写锁 三.悲观锁.乐观锁 3.1 悲观锁 3.2 乐观锁 3.3 CAS操作方式 3.4 CAS算法理解 3.5 CAS(乐观锁算法) 3.6 CAS缺点 四.原子类 4.1 概述 ...

  8. 第三章、前端之JavaScript

    目录 第三章.前端之JavaScript 一.javaScript的引入方式 二.JavaScript语言的规范 三.语言基础 变量声明 四.数据类型 五.流程控制 六.函数 函数的argument ...

  9. java--springmvc

    springmvc请求图 SpringMVC内部的执行流程1.用户发起到达中央调度器DispatcherServlet2.中央调度器DispatcherServlet把请求(some.do)交给了处理 ...

  10. OpenJudge POJ C19C 贪心

    https://cn.vjudge.net/contest/309482#problem/C #include<bits/stdc++.h> using namespace std; ty ...