链接: https://post.icpc-camp.org/d/691-2017
————————————————————————————————————————————————
签到题
注意-2^63 的情况和2^63不能用64位长度的数表示就好了
#include
typedef long long int LL;
using namespace std;
const int N = 200000+7;
inline int read() {
int x=0,f=1;
char ch=getchar();
for(; ch<'0'||'9'if(ch=='-')f=-1;
for(; '0'<=ch&&ch<='9'; ch=getchar()) x=(x<<3)+(x<<1)+ch-'0';
return x*f;
}
/*******************************************************/
int main() {
long double a,b;
while(cin>>a>>b) {
if(a == -9223372036854775808.0) {
// puts("++");
if(a == b) {
puts("1");
} else if(b==-1.0) {
puts("9223372036854775808");
} else if(b==1.0) {
puts("-9223372036854775808");
} else {
LL ans = floor(a/b);
printf("%lld\n",ans);
}
continue;
} else if(b == -9223372036854775808.0) {
if(a<0) puts("-1");
else puts("0");
continue;
}
if(a<0&&b<0) a*=-1.0,b*=-1.0;
// cout << (LL)a <<" "<< (LL)b <
LL ans = floor(a/b);
printf("%lld\n",ans);
}
return 0;
}
————————————————————————————————————————————————
————————————————————————————————————————————————
————————————————————————————————————————————————
给你一个DAG图,每个节点不是白的就是黑的,有q次操作,每次将点x变换颜色.然后输出当前< u,v>有多少对,
< u,v>定义为; 当存在一条从u到v的路径使得路径上没有黑色的点是存在.
考虑到DAG图,所以进行拓扑排序,
每次操作完,之后将黑色的点去掉,然后进行拓扑序,在过程中记录能到达每个点的个数,然后一路算过去就行了,然后去个重复采用vis标记,复杂度是 O(Tqnm) ,然后妥妥的TLE了,
最后想到用二进制来优化,每一位对应表示每一个节点,然后进行TOP过程中与一下就行了.
可以用5个64位整形计算 (这时候注意求1的个数的时候要用lowbit优化)
也可以用bitset来计算
最后复杂度为 O(Tqnm/a) ,其中 a 为bitset优化的常数
#include
typedef long long int LL;
using namespace std;
const int N = 1100+7;
const int MOD = 1e9+7;
inline LL read() {
LL x=0,f=1;
char ch=getchar();
for(; ch<'0'||'9'if(ch=='-')f=-1;
for(; '0'<=ch&&ch<='9'; ch=getchar()) x=(x<<3)+(x<<1)+ch-'0';
return x*f;
}
/*******************************************************/
int n,m,q,ans;
vector<int>G[303];
int vis[303],c[303],deg[303],temp[303];
void TOP() {
bitset<303>mmp[303];
ans = 0;
queue<int>q;
for(int i=1; i<=n; i++) {
if(deg[i]==0) {
q.push(i);
}
temp[i]=deg[i];
}
for(int i=1; i<=n; i++) {
mmp[i][i]=1;
}
while(!q.empty()) {
int u=q.front();
q.pop();
for(int i=0; iint v=G[u][i];
if(c[v]==0&&c[u]==0) {
mmp[v]=mmp[v]|mmp[u];
}
temp[v]--;
if(temp[v]==0)q.push(v);
}
}
for(int i=1; i<=n; i++) {
if(c[i]==0)
ans+=mmp[i].count()-1;
// printf("%d ---%d\n",c[i],mmp[i].count()-1);
}
printf("%d\n",ans);
}
int main() {
while(~scanf("%d%d%d",&n,&m,&q)) {
memset(c,0,sizeof(c));
memset(deg,0,sizeof(deg));
for(int i=1; i<=n; i++)G[i].clear();
for(int i=1,u,v; i<=m; i++) {
scanf("%d%d",&u,&v);
G[u].push_back(v);
deg[v]++;
}
for(int x; q--;) {
scanf("%d",&x);
c[x]=1-c[x];
TOP();
}
}
return 0;
}
————————————————————————————————————————————————
给你个序列 问你去除每个数之后剩下的数中的结果
结果定义为 f21\xorf22\xor...\xorf2n
f(i) 为以 a(i) 结尾的lis的长度
最暴力的想法是求 n 遍 lis 复杂度为 O(n2logn) ,一定TLE, 然后想如何优化为 O(n2)
然后想到删除一个数之后对 f(i) 的影响至多减少1, 所以在我们有了原序列的 f(i) 之后 我们就可以 O(2n) 的求每次新的 f(i)
过程中只要记录 长度为 l 的上升序列当前的最小结尾是谁 ,然后每次看长度为 f[i]−1 的序列的结尾和 a[i] 比谁大 就能判断 f(i) 是否减了1
#include
typedef long long int LL;
using namespace std;
const int N = 5000+7;
const int MOD = 1e9+7;
const int INF = (~(1<<31));
inline LL read() {
LL x=0,f=1;
char ch=getchar();
for(; ch<'0'||'9'if(ch=='-')f=-1;
for(; '0'<=ch&&ch<='9'; ch=getchar()) x=(x<<3)+(x<<1)+ch-'0';
return x*f;
}
/*******************************************************/
int n;
int a[N],b[N],f[N];
int main() {
while(~scanf("%d",&n)) {
for(int i=1; i<=n; i++) scanf("%d",&a[i]);
for(int i=1; i<=n; i++) {
f[i]=1;
for(int j=1; jif(a[i]>a[j])
f[i]=max(f[i],f[j]+1);
}
int ans,tmp;
for(int k=1; k<=n; k++) {
for(int i=1; i<=n; i++) b[i] = INF;
ans = 0;
for(int i=1; i<=n; i++) {
if(i==k) continue;
if(b[f[i]-1] < a[i]) tmp = f[i];
else tmp = f[i]-1;
ans ^= (tmp*tmp);
b[tmp] = min(b[tmp],a[i]);
}
printf("%d%c",ans,(k==n)?'\n':' ');
}
}
return 0;
}
————————————————————————————————————————————————
给你 f(x,y)=ax2+bxy+cy2 ,问你是否永远非负
考虑到数据范围只有 [−10,10] ,于是选择打表,
判断过程是计算 x,y∈[−1000,1000] 过程中有没有负的,然后输出 {0,1}
代码太长了 http://paste.ubuntu.com/25102699/
————————————————————————————————————————————————
给你4个数 a,b,c,d . 0≤a≤b≤109,0≤c≤d≤109
问你 ∑i=ab∑j=cd[i∗j%2017=0]
考虑到2017是素数,满足的情况用坐标系表示的话一定在 x,y=2017k 上 ,所以直接计算就好了
LL cal(LL a,LL b){
LL ans = (a/2017)*b+(b/2017)*a-(a/2017)*(b/2017);
return ans;
}
int main(){
LL a,b,c,d;
while(~scanf("%lld%lld%lld%lld",&a,&b,&c,&d))
printf("%lld\n",cal(b,d)-cal(b,c-1)-cal(a-1,d)+cal(a-1,c-1));
return 0;
}
————————————————————————————————————————————————
————————————————————————————————————————————————
————————————————————————————————————————————————
给你一个n*n的方阵 求每个子矩阵的元素和的三次方的和
其中
a(a2+b2+c2+d2−2ab−2ac+2ad+2bc−2bd−2cd)=a3+ab2+ac2+ad2−2a2b−2a2c+2a2d+2abc−2abd−2acd −b(a2+b2+c2+d2−2ab−2ac+2ad+2bc−2bd−2cd)=−a2b−b3−bc2−bd2+2ab2+2abc−2abd−2b2c+2b2d+2bcd −c(a2+b2+c2+d2−2ab−2ac+2ad+2bc−2bd−2cd)=−a2c−b2c−c3−cd2+2abc+2ac2−2acd−2bc2+2bcd+2c2d d(a2+b2+c2+d2−2ab−2ac+2ad+2bc−2bd−2cd)=a2d+b2d+c2d+d3−2abd−2acd+2ad2+2bcd−2bd2−2cd2.
我TM是有多无聊 会来补这个题,,,MD 不补了
然后在对于每种情况的求一下对结果的贡献系数
然后推到一下 ,就需要在预处理出几种前缀和,后缀和,
然后统计即可 总复杂度是 O(n) 的
代码没写 看dalao的吧
————————————————————————————————————————————————
对于原根理解的十分不到位,只停留到会计算,,,,
算是强行补题.
大概了解下原根在了解些什么是生成元这题就可以做了
将乘法转化为加法
个人理解其实这部分相当去将a*x%2017和a*y%2017的结果进行了优化,能够方便记录每一位的值
考虑dp[i][j] 表示到第i个点后取模结果为j的数的个数 然后优化下空间到dp[2017];
每次转移就是 dp[i][j∗x]+=dp[i−1][j],dp[i][j∗x]
然后因为转化为加法后 能够快速找到值, 又有最后的结果要对 2 取模 能够想到二进制的方法做,
这里采用了bitset
int p[N];
int n,r;
int get(int mod) {
for(int i = 2; ; i++) {
set<int> s;
for(int j = 1, x = 1; j < mod; j++) {
x = (x*i)%mod;
s.insert(x);
}
if(s.size() == mod-1) return i;
}
}
int main() {
// cout << get(2017) << endl;
// 5 为模 2017 的 原根
for(int i = 0, x = 1; i < 2016; i++) {
p[x] = i;
x = (x*5)%2017;
}
while(~scanf("%d%d", &n, &r)) {
bitset<2016> f;
f[p[1]] = 1;
for(int i = 0; i < n; i++) {
int x; scanf("%d", &x); x = p[x];
f ^= (f<>(2016-x));
}
printf("%d\n", (int)f[p[r]]);
}
return 0;
}
————————————————————————————————————————————————
给你一个序列以及
问你 ∑i≤i<j<k<l≤naiajakal
有了s3 , 所以可以先求3个数的情况,然后找第4个数,
然后发现,每次如果第4个数选择 a[x] ,那么结果就多了 a[x]×∑i≤i<j<k<xaiajak
所以遍历一遍序列,即固定 a[l] 同时能求出 ∑i=1nai∑i=1na2i∑i=1na3i 从而能 O(1) 求出 ∑i≤i<j<k<laiajak
#include
typedef long long int LL;
using namespace std;
const int N = 200000+7;
const int MOD = 1e9+7;
inline int read() {
int x=0,f=1;
char ch=getchar();
for(; ch<'0'||'9'if(ch=='-')f=-1;
for(; '0'<=ch&&ch<='9'; ch=getchar()) x=(x<<3)+(x<<1)+ch-'0';
return x*f;
}
/*******************************************************/
LL qmod(LL a,LL b){
LL res = 1ll;
while(b){
if(b&1) res=res*a%MOD;
b>>=1,a=a*a%MOD;
}
return res;
}
int n ;
LL inv6 = qmod(6,MOD-2);
LL a[N];
LL cal(LL a1,LL a2,LL a3){
LL ans = 0;
ans += qmod(a1,3);
ans -= a1*a2%MOD*3%MOD; ans = (ans % MOD + MOD ) %MOD;
ans += a3*2%MOD; ans %= MOD;
return ans*inv6%MOD;
}
int main(){
while(~scanf("%d",&n)){
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
LL a1 = 0,a2 = 0,a3 = 0,ans = 0,tmp = 0;
for(int i=1;i<=n;i++){
if(i>3){
tmp = a[i]*cal(a1,a2,a3)%MOD;
ans += tmp;
ans %= MOD;
}
a1+=a[i];
a2+=a[i]*a[i]%MOD;
a3+=qmod(a[i],3);
a1%=MOD,a2%=MOD,a3%=MOD;
// printf(" %lld --->> %lld \n",tmp,ans);
}
printf("%lld\n",ans%MOD);
}
return 0;
}